source: tags/1.1.0/UAcronym.pas

Last change on this file was 56, checked in by chronos, 8 years ago
  • Added: Show how many new acronyms were imported.
File size: 39.1 KB
Line 
1unit UAcronym;
2
3{$mode delphi}{$H+}
4
5interface
6
7uses
8 Classes, SysUtils, Contnrs, XMLConf, XMLRead, XMLWrite, DOM, UXMLUtils,
9 SpecializedList, fphttpclient, Dialogs, odbcconn, sqldb;
10
11type
12 TAcronymCategories = class;
13 TAcronymMeanings = class;
14 TAcronymDb = class;
15 TImportSources = class;
16 TImportFormats = class;
17
18 TAcronymSource = class
19 Name: string;
20 URL: string;
21 end;
22
23 TAcronymSources = class(TObjectList)
24
25 end;
26
27 { TAcronym }
28
29 TAcronym = class
30 Db: TAcronymDb;
31 Name: string;
32 Meanings: TAcronymMeanings;
33 procedure SaveToNode(Node: TDOMNode);
34 procedure LoadFromNode(Node: TDOMNode);
35 constructor Create;
36 destructor Destroy; override;
37 end;
38
39 { TAcronyms }
40
41 TAcronyms = class(TObjectList)
42 Db: TAcronymDb;
43 procedure SaveToNode(Node: TDOMNode);
44 procedure LoadFromNode(Node: TDOMNode);
45 function SearchByName(Name: string): TAcronym;
46 function AddAcronym(Name: string): TAcronym;
47 end;
48
49 { TAcronymMeaning }
50
51 TAcronymMeaning = class
52 Id: Integer;
53 Name: string;
54 Description: string;
55 Language: string;
56 Acronym: TAcronym;
57 Categories: TAcronymCategories;
58 Source: TAcronymSource;
59 procedure SaveToNode(Node: TDOMNode);
60 procedure LoadFromNode(Node: TDOMNode);
61 constructor Create;
62 destructor Destroy; override;
63 end;
64
65 { TAcronymMeanings }
66
67 TAcronymMeanings = class(TObjectList)
68 public
69 Acronym: TAcronym;
70 procedure UpdateIds;
71 procedure SaveToNode(Node: TDOMNode);
72 procedure LoadFromNode(Node: TDOMNode);
73 function SearchByName(Name: string): TAcronymMeaning;
74 function AddMeaning(Name: string): TAcronymMeaning;
75 end;
76
77 { TAcronymCategory }
78
79 TAcronymCategory = class
80 Id: Integer;
81 Name: string;
82 AcronymMeanings: TAcronymMeanings;
83 procedure SaveToNode(Node: TDOMNode);
84 procedure LoadFromNode(Node: TDOMNode);
85 constructor Create;
86 destructor Destroy; override;
87 end;
88
89 { TAcronymCategories }
90
91 TAcronymCategories = class(TObjectList)
92 Db: TAcronymDb;
93 procedure UpdateIds;
94 procedure SaveToNode(Node: TDOMNode);
95 procedure LoadFromNode(Node: TDOMNode);
96 procedure SaveRefToNode(Node: TDOMNode);
97 procedure LoadRefFromNode(Node: TDOMNode);
98 function SearchByName(Name: string): TAcronymCategory;
99 function SearchById(Id: Integer): TAcronymCategory;
100 function AddContext(Name: string): TAcronymCategory;
101 procedure AssignToStrings(Strings: TStrings);
102 procedure AssignFromStrings(Strings: TStrings);
103 function GetString: string;
104 end;
105
106 { TAcronymEntry }
107
108 TAcronymEntry = class
109 Name: string;
110 Meaning: string;
111 Description: string;
112 Categories: TStringList;
113 constructor Create;
114 destructor Destroy; override;
115 end;
116
117 TImportPatternFlag = (ipfNone, ipfNewItem, ipfSkip, ipfRemove);
118 TImportVariable = (ivNone, ivAcronym, ivMeaning, ivDescription);
119
120 { TImportPattern }
121
122 TImportPattern = class
123 StartString: string;
124 EndString: string;
125 Variable: TImportVariable;
126 Flag: TImportPatternFlag;
127 Repetition: Boolean;
128 procedure Assign(Source: TImportPattern);
129 procedure SaveToNode(Node: TDOMNode);
130 procedure LoadFromNode(Node: TDOMNode);
131 end;
132
133 { TImportPatterns }
134
135 TImportPatterns = class(TObjectList)
136 procedure SaveToNode(Node: TDOMNode);
137 procedure LoadFromNode(Node: TDOMNode);
138 end;
139
140 TImportFormatKind = (ifkParseURL, ifkMSAccess, ifkParseFile);
141
142 { TImportFormat }
143
144 TImportFormat = class
145 Id: Integer;
146 Name: string;
147 Kind: TImportFormatKind;
148 Block: TImportPattern;
149 ItemPatterns: TImportPatterns;
150 Formats: TImportFormats;
151 procedure Assign(Source: TImportFormat);
152 procedure SaveToNode(Node: TDOMNode);
153 procedure LoadFromNode(Node: TDOMNode);
154 constructor Create;
155 destructor Destroy; override;
156 end;
157
158 { TImportFormats }
159
160 TImportFormats = class(TObjectList)
161 procedure UpdateIds;
162 procedure SaveToNode(Node: TDOMNode);
163 procedure LoadFromNode(Node: TDOMNode);
164 function SearchByName(Name: string): TImportFormat;
165 function SearchById(Id: Integer): TImportFormat;
166 end;
167
168 { TImportSource }
169
170 TImportSource = class
171 private
172 ResponseStream: TMemoryStream;
173 procedure DoPassword(Sender: TObject; var RepeatRequest : Boolean);
174 procedure TextParse(S: string);
175 public
176 Enabled: Boolean;
177 Name: string;
178 URL: string;
179 Format: TImportFormat;
180 LastTime: TDateTime;
181 Sources: TImportSources;
182 ItemCount: Integer;
183 LastImportTime: TDateTime;
184 Categories: TAcronymCategories;
185 UserName: string;
186 Password: string;
187 function DownloadHTTP(URL: string; Stream: TStream): Boolean;
188 procedure Process;
189 procedure ProcessTextParseURL;
190 procedure ProcessTextParseFile;
191 procedure ProcessMSAccess;
192 procedure Assign(Source: TImportSource);
193 procedure SaveToNode(Node: TDOMNode);
194 procedure LoadFromNode(Node: TDOMNode);
195 constructor Create;
196 destructor Destroy; override;
197 end;
198
199 { TImportSources }
200
201 TImportSources = class(TObjectList)
202 AcronymDb: TAcronymDb;
203 function SearchByName(Name: string): TImportSource;
204 procedure SaveToNode(Node: TDOMNode);
205 procedure LoadFromNode(Node: TDOMNode);
206 end;
207
208 { TAcronymDb }
209
210 TAcronymDb = class
211 FileName: string;
212 Sources: TAcronymSources;
213 Acronyms: TAcronyms;
214 Categories: TAcronymCategories;
215 ImportSources: TImportSources;
216 ImportFormats: TImportFormats;
217 Modified: Boolean;
218 AddedCount: Integer;
219 constructor Create;
220 destructor Destroy; override;
221 procedure LoadFromFile(FileName: string);
222 procedure SaveToFile(FileName: string);
223 procedure LoadFromFileCSV(FileName: string);
224 procedure SaveToFileCSV(FileName: string);
225 procedure FilterList(AName: string; Items: TAcronymMeanings);
226 function AddAcronym(AcronymName, MeaningName: string): TAcronymMeaning;
227 procedure RemoveMeaning(Meaning: TAcronymMeaning);
228 procedure RemoveAcronym(AcronymName, MeaningName: string);
229 procedure AssignToList(List: TListObject);
230 end;
231
232function AcronymComparer(Item1, Item2: Pointer): Integer;
233
234var
235 ImportVariableString: array [TImportVariable] of string;
236 ImportPatternFlagString: array [TImportPatternFlag] of string;
237
238procedure Translate;
239
240implementation
241
242resourcestring
243 SWrongFileFormat = 'Wrong file format';
244 SUnsupportedImportFormat = 'Unsupported import format';
245 SDescription = 'Description';
246 SMeaning = 'Meaning';
247 SAcronym = 'Acronym';
248 SNone = 'None';
249 SNewItem = 'New item';
250 SSkip = 'Skip';
251 SRemoveOnStart = 'Remove on start';
252 SUnsupportedAuthMethod = 'Unsupported HTTP authorization method';
253 SFileNotFound = 'File %s not found';
254
255
256procedure Translate;
257begin
258 ImportVariableString[ivAcronym] := SAcronym;
259 ImportVariableString[ivNone] := SNone;
260 ImportVariableString[ivMeaning] := SMeaning;
261 ImportVariableString[ivDescription] := SDescription;
262 ImportPatternFlagString[ipfNone] := SNone;
263 ImportPatternFlagString[ipfNewItem] := SNewItem;
264 ImportPatternFlagString[ipfSkip] := SSkip;
265 ImportPatternFlagString[ipfRemove] := SRemoveOnStart;
266end;
267
268function AcronymComparer(Item1, Item2: Pointer): Integer;
269begin
270 Result := CompareStr(TAcronym(Item1).Name, TAcronym(Item2).Name);
271end;
272
273function StripHTML(S: string): string;
274var
275 TagBegin, TagEnd, TagLength: Integer;
276begin
277 TagBegin := Pos( '<', S); // search position of first <
278
279 while (TagBegin > 0) do begin // while there is a < in S
280 TagEnd := Pos('>', S); // find the matching >
281 if TagEnd = 0 then TagLength := Length(S) - TagBegin
282 else TagLength := TagEnd - TagBegin + 1;
283 if TagLength > 0 then
284 Delete(S, TagBegin, TagLength) // delete the tag
285 else Delete(S, 1, TagEnd); // delete the tag
286 TagBegin := Pos( '<', S); // search for next <
287 end;
288
289 Result := S; // give the result
290end;
291
292{ TImportSourceMSAccess }
293
294procedure TImportSource.ProcessMSAccess;
295var
296 ODBCConnection1: TODBCConnection;
297 SQLTransaction1: TSQLTransaction;
298 SQLQuery1: TSQLQuery;
299 NewAcronym: TAcronymEntry;
300begin
301 ItemCount := 0;
302 ODBCConnection1 := TODBCCOnnection.Create(nil);
303 SQLQuery1 := TSQLQuery.Create(nil);
304 SQLTransaction1 := TSQLTransaction.Create(nil);
305 try
306 ODBCConnection1.Driver := 'Microsoft Access Driver (*.mdb, *.accdb)';
307 ODBCConnection1.Params.Add('DBQ=' + URL);
308 ODBCConnection1.Params.Add('Locale Identifier=1031');
309 ODBCConnection1.Params.Add('ExtendedAnsiSQL=1');
310 ODBCConnection1.Params.Add('CHARSET=ansi');
311 ODBCConnection1.Connected := True;
312 ODBCConnection1.KeepConnection := True;
313
314 SQLTransaction1.DataBase := ODBCConnection1;
315 SQLTransaction1.Action := caCommit;
316 SQLTransaction1.Active := True;
317
318 SQLQuery1.DataBase := ODBCConnection1;
319 SQLQuery1.UsePrimaryKeyAsKey := False;
320 SQLQuery1.SQL.Text := 'SELECT Acronym,Meaning FROM data1';
321 SQLQuery1.Open;
322
323 NewAcronym := TAcronymEntry.Create;
324 while not SQLQuery1.EOF do begin
325 NewAcronym.Name := SQLQuery1.FieldByName('Acronym').AsString;
326 NewAcronym.Meaning := SQLQuery1.FieldByName('Meaning').AsString;
327 if (NewAcronym.Name <> '') and (NewAcronym.Meaning <> '') then
328 Sources.AcronymDb.AddAcronym(NewAcronym.Name, NewAcronym.Meaning);
329 SQLQuery1.Next;
330 Inc(ItemCount);
331 end;
332 NewAcronym.Free;
333 finally
334 SQLQuery1.Free;
335 SQLTransaction1.Free;
336 ODBCConnection1.Free;
337 end;
338end;
339
340{ TImportPatterns }
341
342procedure TImportPatterns.SaveToNode(Node: TDOMNode);
343var
344 I: Integer;
345 NewNode2: TDOMNode;
346begin
347 for I := 0 to Count - 1 do
348 with TImportPattern(Items[I]) do begin
349 NewNode2 := Node.OwnerDocument.CreateElement('Pattern');
350 Node.AppendChild(NewNode2);
351 SaveToNode(NewNode2);
352 end;
353end;
354
355procedure TImportPatterns.LoadFromNode(Node: TDOMNode);
356var
357 Node2: TDOMNode;
358 NewItem: TImportPattern;
359begin
360 Count := 0;
361 Node2 := Node.FirstChild;
362 while Assigned(Node2) and (Node2.NodeName = 'Pattern') do begin
363 NewItem := TImportPattern.Create;
364 NewItem.LoadFromNode(Node2);
365 Add(NewItem);
366 Node2 := Node2.NextSibling;
367 end;
368end;
369
370{ TImportPattern }
371
372procedure TImportPattern.Assign(Source: TImportPattern);
373begin
374 StartString := Source.StartString;
375 EndString := Source.EndString;
376 Variable := Source.Variable;
377 Flag := Source.Flag;
378 Repetition := Source.Repetition;
379end;
380
381procedure TImportPattern.SaveToNode(Node: TDOMNode);
382begin
383 WriteString(Node, 'StartString', StartString);
384 WriteString(Node, 'EndString', EndString);
385 WriteInteger(Node, 'Variable', Integer(Variable));
386 WriteInteger(Node, 'Flag', Integer(Flag));
387 WriteBoolean(Node, 'Repetition', Repetition);
388end;
389
390procedure TImportPattern.LoadFromNode(Node: TDOMNode);
391begin
392 StartString := ReadString(Node, 'StartString', '');
393 EndString := ReadString(Node, 'EndString', '');
394 Variable := TImportVariable(ReadInteger(Node, 'Variable', 0));
395 Flag := TImportPatternFlag(ReadInteger(Node, 'Flag', 0));
396 Repetition := ReadBoolean(Node, 'Repetition', False);
397end;
398
399procedure TImportSource.DoPassword(Sender: TObject; var RepeatRequest: Boolean);
400var
401 H: string;
402begin
403 with TFPHttpClient(Sender) do begin
404 H := GetHeader(ResponseHeaders, 'WWW-Authenticate');
405 if Pos(' ', H) > 0 then H := Copy(H, 1, Pos(' ', H) - 1);
406
407 if H <> 'Basic' then
408 raise Exception.Create(SUnsupportedAuthMethod);
409
410 if (Self.UserName <> '') and (UserName = '') then begin
411 UserName := Self.UserName;
412 Password := Self.Password;
413 ResponseStream.Clear;
414 RepeatRequest := True;
415 end else RepeatRequest := False;
416 end;
417end;
418
419procedure TImportSource.TextParse(S: string);
420var
421 SS: string;
422 NewAcronym: TAcronymEntry;
423 P: Integer;
424 P1, P2: Integer;
425 Q: Integer;
426 I: Integer;
427 T: string;
428 LastLength: Integer;
429 AddedAcronym: TAcronymMeaning;
430begin
431 ItemCount := 0;
432 NewAcronym := TAcronymEntry.Create;
433 try
434
435 // Find main block
436 if Format.Block.StartString <> '' then begin
437 P := Pos(Format.Block.StartString, S);
438 if P > 0 then
439 Delete(S, 1, P + Length(Format.Block.StartString) - 1);
440 end;
441 if Format.Block.EndString <> '' then begin
442 P := Pos(Format.Block.EndString, S);
443 if P > 0 then
444 Delete(S, P, Length(S));
445 end;
446
447 // Remove unneeded items
448 repeat
449 LastLength := Length(S);
450 for I := 0 to Format.ItemPatterns.Count - 1 do
451 with TImportPattern(Format.ItemPatterns[I]) do
452 if Flag = ipfRemove then begin
453 P := Pos(StartString, S);
454 if P > 0 then begin
455 SS := Copy(S, P + Length(StartString), Length(S));
456 Q := Pos(EndString, SS);
457 if Q > 0 then begin
458 Delete(S, P, Q + Length(EndString) + Length(StartString) - 1);
459 end;
460 end;
461 end;
462 until Length(S) = LastLength;
463
464 // Find items
465 repeat
466 LastLength := Length(S);
467 I := 0;
468 while I < Format.ItemPatterns.Count do
469 with TImportPattern(Format.ItemPatterns[I]) do begin
470 if Flag <> ipfRemove then begin
471 if Length(StartString) > 0 then begin
472 P := Pos(StartString, S);
473 if P > 0 then Delete(S, 1, P + Length(StartString) - 1);
474 end;
475
476 if ((Length(StartString) > 0) and (P > 0)) or (Length(StartString) = 0) then begin
477 P := Pos(EndString, S);
478 T := Copy(S, 1, P - 1);
479 if Flag <> ipfSkip then begin
480 T := StripHTML(T);
481 T := StringReplace(T, '&quot;', '"', [rfReplaceAll]);
482 T := StringReplace(T, '&trade;', 'TM', [rfReplaceAll]);
483 T := StringReplace(T, '&amp;', '&', [rfReplaceAll]);
484 T := StringReplace(T, '&#160;', ' ', [rfReplaceAll]); // No break space
485 T := Trim(T);
486 case Variable of
487 ivAcronym: NewAcronym.Name := T;
488 ivMeaning: NewAcronym.Meaning := T;
489 ivDescription: NewAcronym.Description := T;
490 end;
491 end;
492 Delete(S, 1, P + Length(EndString) - 1);
493
494 if (Flag = ipfNewItem) and (NewAcronym.Name <> '') and
495 (NewAcronym.Meaning <> '') then begin
496 AddedAcronym := Sources.AcronymDb.AddAcronym(NewAcronym.Name, NewAcronym.Meaning);
497 AddedAcronym.Description := NewAcronym.Description;
498 AddedAcronym.Categories.Assign(Categories, laOr);
499 Inc(ItemCount);
500 end;
501
502 if Repetition then begin
503 if Length(StartString) > 0 then begin
504 P1 := Pos(StartString, S);
505 if P1 > 0 then begin
506 P2 := Pos(TImportPattern(Format.ItemPatterns[(I + 1) mod Format.ItemPatterns.Count]).StartString, S);
507 if (P2 > 0) and (P1 < P2) then Continue;
508 end;
509 end;
510 end;
511 end;
512 end;
513 Inc(I);
514 end;
515 until Length(S) = LastLength;
516 finally
517 NewAcronym.Free;
518 end;
519end;
520
521
522function TImportSource.DownloadHTTP(URL: string; Stream: TStream): Boolean;
523var
524 HTTPClient: TFPHTTPClient;
525 FormData: TStringList;
526begin
527 Result := False;
528 HTTPClient := TFPHttpClient.Create(nil);
529 HTTPClient.AllowRedirect := True;
530 HTTPClient.OnPassword := DoPassword;
531 FormData := TStringList.Create;
532 try
533 HTTPClient.Get(URL, Stream);
534 Result := True;
535 finally
536 FormData.Free;
537 HTTPClient.Free;
538 end;
539end;
540
541procedure TImportSource.Process;
542begin
543 case Format.Kind of
544 ifkParseURL: ProcessTextParseURL;
545 ifkMSAccess: ProcessMSAccess;
546 ifkParseFile: ProcessTextParseFile;
547 else raise Exception.Create(SUnsupportedImportFormat);
548 end;
549 LastImportTime := Now;
550end;
551
552
553{ TImportFormat }
554
555procedure TImportFormat.Assign(Source: TImportFormat);
556var
557 I: Integer;
558begin
559 Kind := Source.Kind;
560 Name := Source.Name;
561 Block.StartString := Source.Block.StartString;
562 Block.EndString := Source.Block.EndString;
563 while ItemPatterns.Count < Source.ItemPatterns.Count do
564 ItemPatterns.Add(TImportPattern.Create);
565 if ItemPatterns.Count > Source.ItemPatterns.Count then
566 ItemPatterns.Count := Source.ItemPatterns.Count;
567 for I := 0 to ItemPatterns.Count - 1 do begin
568 TImportPattern(ItemPatterns[I]).Assign(TImportPattern(Source.ItemPatterns[I]));
569 end;
570end;
571
572procedure TImportFormat.SaveToNode(Node: TDOMNode);
573var
574 NewNode: TDOMNode;
575begin
576 WriteInteger(Node, 'Id', Id);
577 WriteString(Node, 'Name', Name);
578 WriteInteger(Node, 'Kind', Integer(Kind));
579 WriteString(Node, 'BlockStartString', Block.StartString);
580 WriteString(Node, 'BlockEndString', Block.EndString);
581
582 NewNode := Node.OwnerDocument.CreateElement('Patterns');
583 Node.AppendChild(NewNode);
584 ItemPatterns.SaveToNode(NewNode);
585end;
586
587procedure TImportFormat.LoadFromNode(Node: TDOMNode);
588var
589 NewNode: TDOMNode;
590begin
591 Id := ReadInteger(Node, 'Id', 0);
592 Name := ReadString(Node, 'Name', '');
593 Kind := TImportFormatKind(ReadInteger(Node, 'Kind', 0));
594 Block.StartString := ReadString(Node, 'BlockStartString', '');
595 Block.EndString := ReadString(Node, 'BlockEndString', '');
596
597 NewNode := Node.FindNode('Patterns');
598 if Assigned(NewNode) then
599 ItemPatterns.LoadFromNode(NewNode);
600end;
601
602constructor TImportFormat.Create;
603begin
604 Block := TImportPattern.Create;
605 ItemPatterns := TImportPatterns.Create;
606end;
607
608destructor TImportFormat.Destroy;
609begin
610 Block.Free;
611 ItemPatterns.Free;
612 inherited Destroy;
613end;
614
615{ TImportSources }
616
617function TImportSources.SearchByName(Name: string): TImportSource;
618var
619 I: Integer;
620begin
621 I := 0;
622 while (I < Count) and (TImportSource(Items[I]).Name <> Name) do Inc(I);
623 if I < Count then Result := TImportSource(Items[I])
624 else Result := nil;
625end;
626
627procedure TImportSources.SaveToNode(Node: TDOMNode);
628var
629 I: Integer;
630 NewNode2: TDOMNode;
631begin
632 for I := 0 to Count - 1 do
633 with TImportSource(Items[I]) do begin
634 NewNode2 := Node.OwnerDocument.CreateElement('ImportSource');
635 Node.AppendChild(NewNode2);
636 SaveToNode(NewNode2);
637 end;
638end;
639
640procedure TImportSources.LoadFromNode(Node: TDOMNode);
641var
642 Node2: TDOMNode;
643 NewItem: TImportSource;
644begin
645 Count := 0;
646 Node2 := Node.FirstChild;
647 while Assigned(Node2) and (Node2.NodeName = 'ImportSource') do begin
648 NewItem := TImportSource.Create;
649 NewItem.Sources := Self;
650 NewItem.LoadFromNode(Node2);
651 Add(NewItem);
652 Node2 := Node2.NextSibling;
653 end;
654end;
655
656{ TImportFormats }
657
658function TImportFormats.SearchByName(Name: string): TImportFormat;
659var
660 I: Integer;
661begin
662 I := 0;
663 while (I < Count) and (TImportFormat(Items[I]).Name <> Name) do Inc(I);
664 if I < Count then Result := TImportFormat(Items[I])
665 else Result := nil;
666end;
667
668procedure TImportFormats.UpdateIds;
669var
670 LastId: Integer;
671 I: Integer;
672begin
673 // Get highest used ID
674 LastId := 0;
675 for I := 0 to Count - 1 do begin
676 if TImportFormat(Items[I]).Id > LastId then LastId := TImportFormat(Items[I]).Id;
677 end;
678 // Add ID to new items without ID
679 for I := 0 to Count - 1 do begin
680 if TImportFormat(Items[I]).Id = 0 then begin
681 Inc(LastId);
682 TImportFormat(Items[I]).Id := LastId;
683 end;
684 end;
685end;
686
687procedure TImportFormats.SaveToNode(Node: TDOMNode);
688var
689 I: Integer;
690 NewNode2: TDOMNode;
691begin
692 UpdateIds;
693 for I := 0 to Count - 1 do
694 with TImportFormat(Items[I]) do begin
695 NewNode2 := Node.OwnerDocument.CreateElement('ImportFormat');
696 Node.AppendChild(NewNode2);
697 SaveToNode(NewNode2);
698 end;
699end;
700
701procedure TImportFormats.LoadFromNode(Node: TDOMNode);
702var
703 Node2: TDOMNode;
704 NewItem: TImportFormat;
705begin
706 Count := 0;
707 Node2 := Node.FirstChild;
708 while Assigned(Node2) and (Node2.NodeName = 'ImportFormat') do begin
709 NewItem := TImportFormat.Create;
710 NewItem.LoadFromNode(Node2);
711 Add(NewItem);
712 Node2 := Node2.NextSibling;
713 end;
714 UpdateIds;
715end;
716
717function TImportFormats.SearchById(Id: Integer): TImportFormat;
718var
719 I: Integer;
720begin
721 I := 0;
722 while (I < Count) and (TImportFormat(Items[I]).Id <> Id) do Inc(I);
723 if I < Count then Result := TImportFormat(Items[I])
724 else Result := nil;
725end;
726
727{ TImportSource }
728
729procedure TImportSource.ProcessTextParseURL;
730var
731 S: string;
732begin
733 if DownloadHTTP(URL, ResponseStream) then begin
734 ResponseStream.Position := 0;
735 SetLength(S, ResponseStream.Size);
736 ResponseStream.Read(S[1], Length(S));
737
738 TextParse(S);
739 end;
740end;
741
742procedure TImportSource.ProcessTextParseFile;
743var
744 S: TStringList;
745begin
746 if FileExists(URL) then begin
747 S := TStringList.Create;
748 try
749 S.LoadFromFile(URL);
750 TextParse(S.Text);
751 finally
752 S.Free;
753 end;
754 end else ShowMessage(SysUtils.Format(SFileNotFound, [URL]));
755end;
756
757procedure TImportSource.Assign(Source: TImportSource);
758begin
759 Enabled := Source.Enabled;
760 Name := Source.Name;
761 URL := Source.URL;
762 Format := Source.Format;
763 LastTime := Source.LastTime;
764 ItemCount := Source.ItemCount;
765 Categories.Assign(Source.Categories);
766 UserName := Source.UserName;
767 Password := Source.Password;
768 LastImportTime := Source.LastImportTime;
769end;
770
771procedure TImportSource.SaveToNode(Node: TDOMNode);
772var
773 NewNode: TDOMNode;
774begin
775 WriteString(Node, 'Name', Name);
776 WriteString(Node, 'URL', URL);
777 if Assigned(Format) then WriteInteger(Node, 'ImportFormat', Format.Id)
778 else WriteInteger(Node, 'ImportFormat', -1);
779 WriteBoolean(Node, 'Enabled', Enabled);
780 WriteInteger(Node, 'ItemCount', ItemCount);
781 WriteDateTime(Node, 'LastImportTime', LastImportTime);
782 WriteString(Node, 'UserName', UserName);
783
784 NewNode := Node.OwnerDocument.CreateElement('Categories');
785 Node.AppendChild(NewNode);
786 Categories.SaveRefToNode(NewNode);
787end;
788
789procedure TImportSource.LoadFromNode(Node: TDOMNode);
790var
791 Node2: TDOMNode;
792begin
793 Name := ReadString(Node, 'Name', '');
794 URL := ReadString(Node, 'URL', '');
795 Format := Sources.AcronymDb.ImportFormats.SearchById(ReadInteger(Node, 'ImportFormat', -1));
796 Enabled := ReadBoolean(Node, 'Enabled', True);
797 ItemCount := ReadInteger(Node, 'ItemCount', 0);
798 UserName := ReadString(Node, 'UserName', '');
799 LastImportTime := ReadDateTime(Node, 'LastImportTime', 0);
800
801 Categories.Db := Sources.AcronymDb;
802 Node2 := Node.FindNode('Categories');
803 if Assigned(Node2) then
804 Categories.LoadRefFromNode(Node2);
805end;
806
807constructor TImportSource.Create;
808begin
809 Format := nil;
810 Enabled := True;
811 Categories := TAcronymCategories.Create;
812 Categories.OwnsObjects := False;
813 ResponseStream := TMemoryStream.Create;
814end;
815
816destructor TImportSource.Destroy;
817begin
818 FreeAndNil(ResponseStream);
819 FreeAndNil(Categories);
820 inherited Destroy;
821end;
822
823{ TAcronymEntry }
824
825constructor TAcronymEntry.Create;
826begin
827 Categories := TStringList.Create;
828 Name := '';
829 Meaning := '';
830 Description := '';
831end;
832
833destructor TAcronymEntry.Destroy;
834begin
835 FreeAndNil(Categories);
836 inherited Destroy;
837end;
838
839{ TAcronymMeanings }
840
841procedure TAcronymMeanings.UpdateIds;
842var
843 LastId: Integer;
844 I: Integer;
845begin
846 // Get highest used ID
847 LastId := 0;
848 for I := 0 to Count - 1 do begin
849 if TAcronymMeaning(Items[I]).Id > LastId then LastId := TAcronymMeaning(Items[I]).Id;
850 end;
851 // Add ID to new items without ID
852 for I := 0 to Count - 1 do begin
853 if TAcronymMeaning(Items[I]).Id = 0 then begin
854 Inc(LastId);
855 TAcronymMeaning(Items[I]).Id := LastId;
856 end;
857 end;
858end;
859
860procedure TAcronymMeanings.SaveToNode(Node: TDOMNode);
861var
862 I: Integer;
863 NewNode2: TDOMNode;
864begin
865 UpdateIds;
866 for I := 0 to Count - 1 do
867 with TAcronymMeaning(Items[I]) do begin
868 NewNode2 := Node.OwnerDocument.CreateElement('Meaning');
869 Node.AppendChild(NewNode2);
870 SaveToNode(NewNode2);
871 end;
872end;
873
874procedure TAcronymMeanings.LoadFromNode(Node: TDOMNode);
875var
876 Node2: TDOMNode;
877 NewItem: TAcronymMeaning;
878begin
879 Count := 0;
880 Node2 := Node.FirstChild;
881 while Assigned(Node2) and (Node2.NodeName = 'Meaning') do begin
882 NewItem := TAcronymMeaning.Create;
883 NewItem.Acronym := Acronym;
884 NewItem.LoadFromNode(Node2);
885 Add(NewItem);
886 Node2 := Node2.NextSibling;
887 end;
888 UpdateIds;
889end;
890
891function TAcronymMeanings.SearchByName(Name: string): TAcronymMeaning;
892var
893 I: Integer;
894begin
895 I := 0;
896 while (I < Count) and (TAcronymMeaning(Items[I]).Name <> Name) do Inc(I);
897 if I < Count then Result := TAcronymMeaning(Items[I])
898 else Result := nil;
899end;
900
901function TAcronymMeanings.AddMeaning(Name: string): TAcronymMeaning;
902begin
903 Result := TAcronymMeaning.Create;
904 Result.Name := Name;
905 Add(Result);
906end;
907
908{ TAcronymMeaning }
909
910procedure TAcronymMeaning.SaveToNode(Node: TDOMNode);
911var
912 NewNode: TDOMNode;
913begin
914 WriteString(Node, 'Name', Name);
915 WriteString(Node, 'Description', Description);
916 WriteString(Node, 'Language', Language);
917
918 NewNode := Node.OwnerDocument.CreateElement('Categories');
919 Node.AppendChild(NewNode);
920 Categories.SaveRefToNode(NewNode);
921end;
922
923procedure TAcronymMeaning.LoadFromNode(Node: TDOMNode);
924var
925 Node2: TDOMNode;
926 I: Integer;
927begin
928 Name := ReadString(Node, 'Name', '');
929 Description := ReadString(Node, 'Description', '');
930 Language := ReadString(Node, 'Language', '');
931
932 Categories.Db := Acronym.Db;
933 Node2 := Node.FindNode('Categories');
934 if Assigned(Node2) then begin
935 Categories.LoadRefFromNode(Node2);
936
937 // Add reverse references
938 for I := 0 to Categories.Count - 1 do
939 TAcronymCategory(Categories[I]).AcronymMeanings.Add(Self);
940 end;
941end;
942
943constructor TAcronymMeaning.Create;
944begin
945 Categories := TAcronymCategories.Create(False);
946end;
947
948destructor TAcronymMeaning.Destroy;
949var
950 I: Integer;
951begin
952 for I := 0 to Categories.Count - 1 do
953 TAcronymCategory(Categories[I]).AcronymMeanings.Remove(Self);
954 FreeAndNil(Categories);
955 inherited Destroy;
956end;
957
958{ TAcronyms }
959
960procedure TAcronyms.SaveToNode(Node: TDOMNode);
961var
962 I: Integer;
963 NewNode2: TDOMNode;
964begin
965 for I := 0 to Count - 1 do
966 with TAcronym(Items[I]) do begin
967 NewNode2 := Node.OwnerDocument.CreateElement('Acronym');
968 Node.AppendChild(NewNode2);
969 SaveToNode(NewNode2);
970 end;
971end;
972
973procedure TAcronyms.LoadFromNode(Node: TDOMNode);
974var
975 Node2: TDOMNode;
976 NewItem: TAcronym;
977begin
978 Count := 0;
979 Node2 := Node.FirstChild;
980 while Assigned(Node2) and (Node2.NodeName = 'Acronym') do begin
981 NewItem := TAcronym.Create;
982 NewItem.Db := Db;
983 NewItem.LoadFromNode(Node2);
984 Add(NewItem);
985 Node2 := Node2.NextSibling;
986 end;
987end;
988
989function TAcronyms.SearchByName(Name: string): TAcronym;
990var
991 I: Integer;
992begin
993 I := 0;
994 while (I < Count) and (TAcronym(Items[I]).Name <> Name) do Inc(I);
995 if I < Count then Result := TAcronym(Items[I])
996 else Result := nil;
997end;
998
999function TAcronyms.AddAcronym(Name: string): TAcronym;
1000begin
1001 Result := TAcronym.Create;
1002 Result.Name := Name;
1003 Add(Result);
1004end;
1005
1006{ TAcronymCategories }
1007
1008procedure TAcronymCategories.UpdateIds;
1009var
1010 LastId: Integer;
1011 I: Integer;
1012begin
1013 // Get highest used ID
1014 LastId := 0;
1015 for I := 0 to Count - 1 do begin
1016 if TAcronymCategory(Items[I]).Id > LastId then LastId := TAcronymCategory(Items[I]).Id;
1017 end;
1018 // Add ID to new items without ID
1019 for I := 0 to Count - 1 do begin
1020 if TAcronymCategory(Items[I]).Id = 0 then begin
1021 Inc(LastId);
1022 TAcronymCategory(Items[I]).Id := LastId;
1023 end;
1024 end;
1025end;
1026
1027procedure TAcronymCategories.SaveToNode(Node: TDOMNode);
1028var
1029 I: Integer;
1030 NewNode2: TDOMNode;
1031begin
1032 UpdateIds;
1033 for I := 0 to Count - 1 do
1034 with TAcronymCategory(Items[I]) do begin
1035 NewNode2 := Node.OwnerDocument.CreateElement('Category');
1036 Node.AppendChild(NewNode2);
1037 SaveToNode(NewNode2);
1038 end;
1039end;
1040
1041procedure TAcronymCategories.LoadFromNode(Node: TDOMNode);
1042var
1043 Node2: TDOMNode;
1044 NewItem: TAcronymCategory;
1045begin
1046 Count := 0;
1047 Node2 := Node.FirstChild;
1048 while Assigned(Node2) and (Node2.NodeName = 'Category') do begin
1049 NewItem := TAcronymCategory.Create;
1050 NewItem.LoadFromNode(Node2);
1051 Add(NewItem);
1052 Node2 := Node2.NextSibling;
1053 end;
1054 UpdateIds;
1055end;
1056
1057procedure TAcronymCategories.SaveRefToNode(Node: TDOMNode);
1058var
1059 I: Integer;
1060 NewNode: TDOMNode;
1061begin
1062 for I := 0 to Count - 1 do begin
1063 NewNode := Node.OwnerDocument.CreateElement('Category');
1064 Node.AppendChild(NewNode);
1065 WriteInteger(NewNode, 'Id', TAcronymCategory(Items[I]).Id);
1066 end;
1067end;
1068
1069procedure TAcronymCategories.LoadRefFromNode(Node: TDOMNode);
1070var
1071 Node2: TDOMNode;
1072 Id: Integer;
1073 Category: TAcronymCategory;
1074begin
1075 Node2 := Node.FirstChild;
1076 while Assigned(Node2) and (Node2.NodeName = 'Category') do begin
1077 Id := ReadInteger(Node2, 'Id', 0);
1078 Category := Db.Categories.SearchById(Id);
1079 if Assigned(Category) then begin
1080 Add(Category);
1081 end;
1082 Node2 := Node2.NextSibling;
1083 end;
1084end;
1085
1086function TAcronymCategories.SearchByName(Name: string): TAcronymCategory;
1087var
1088 I: Integer;
1089begin
1090 I := 0;
1091 while (I < Count) and (TAcronymCategory(Items[I]).Name <> Name) do Inc(I);
1092 if I < Count then Result := TAcronymCategory(Items[I])
1093 else Result := nil;
1094end;
1095
1096function TAcronymCategories.SearchById(Id: Integer): TAcronymCategory;
1097var
1098 I: Integer;
1099begin
1100 I := 0;
1101 while (I < Count) and (TAcronymCategory(Items[I]).Id <> Id) do Inc(I);
1102 if I < Count then Result := TAcronymCategory(Items[I])
1103 else Result := nil;
1104end;
1105
1106function TAcronymCategories.AddContext(Name: string): TAcronymCategory;
1107begin
1108 Result := TAcronymCategory.Create;
1109 Result.Name := Name;
1110 Add(Result);
1111end;
1112
1113procedure TAcronymCategories.AssignToStrings(Strings: TStrings);
1114var
1115 I: Integer;
1116begin
1117 Strings.Clear;
1118 for I := 0 to Count - 1 do
1119 Strings.AddObject(TAcronymCategory(Items[I]).Name, Items[I]);
1120end;
1121
1122procedure TAcronymCategories.AssignFromStrings(Strings: TStrings);
1123var
1124 I: Integer;
1125begin
1126 Clear;
1127 for I := 0 to Strings.Count - 1 do begin
1128 Add(TAcronymCategory(Strings.Objects[I]));
1129 end;
1130end;
1131
1132function TAcronymCategories.GetString: string;
1133var
1134 I: Integer;
1135begin
1136 Result := '';
1137 for I := 0 to Count - 1 do
1138 Result := Result + TAcronymCategory(Items[I]).Name + ',';
1139 System.Delete(Result, Length(Result), 1);
1140end;
1141
1142
1143{ TAcronym }
1144
1145procedure TAcronym.SaveToNode(Node: TDOMNode);
1146var
1147 NewNode: TDOMNode;
1148begin
1149 WriteString(Node, 'Name', Name);
1150
1151 NewNode := Node.OwnerDocument.CreateElement('Meanings');
1152 Node.AppendChild(NewNode);
1153 Meanings.SaveToNode(NewNode);
1154end;
1155
1156procedure TAcronym.LoadFromNode(Node: TDOMNode);
1157var
1158 NewNode: TDOMNode;
1159begin
1160 Name := ReadString(Node, 'Name', '');
1161
1162 NewNode := Node.FindNode('Meanings');
1163 if Assigned(NewNode) then
1164 Meanings.LoadFromNode(NewNode);
1165end;
1166
1167constructor TAcronym.Create;
1168begin
1169 Meanings := TAcronymMeanings.Create;
1170 Meanings.Acronym := Self;
1171end;
1172
1173destructor TAcronym.Destroy;
1174begin
1175 FreeAndNil(Meanings);
1176 inherited Destroy;
1177end;
1178
1179{ TAcronymCategory }
1180
1181procedure TAcronymCategory.SaveToNode(Node: TDOMNode);
1182begin
1183 WriteString(Node, 'Name', Name);
1184 WriteInteger(Node, 'Id', Id);
1185end;
1186
1187procedure TAcronymCategory.LoadFromNode(Node: TDOMNode);
1188begin
1189 Name := ReadString(Node, 'Name', '');
1190 Id := ReadInteger(Node, 'Id', 0);
1191end;
1192
1193constructor TAcronymCategory.Create;
1194begin
1195 AcronymMeanings := TAcronymMeanings.Create(False);
1196end;
1197
1198destructor TAcronymCategory.Destroy;
1199var
1200 I: Integer;
1201begin
1202 for I := 0 to AcronymMeanings.Count - 1 do
1203 TAcronymMeaning(AcronymMeanings[I]).Categories.Remove(Self);
1204 FreeAndNil(AcronymMeanings);
1205 inherited Destroy;
1206end;
1207
1208{ TAcronymDb }
1209
1210constructor TAcronymDb.Create;
1211begin
1212 Sources := TAcronymSources.Create;
1213 Acronyms := TAcronyms.Create;
1214 Acronyms.Db := Self;
1215 Categories := TAcronymCategories.Create;
1216 ImportSources := TImportSources.Create;
1217 ImportSources.AcronymDb := Self;
1218 ImportFormats := TImportFormats.Create;
1219end;
1220
1221destructor TAcronymDb.Destroy;
1222begin
1223 FreeAndNil(ImportFormats);
1224 FreeAndNil(ImportSources);
1225 FreeAndNil(Sources);
1226 FreeAndNil(Acronyms);
1227 FreeAndNil(Categories);
1228 inherited Destroy;
1229end;
1230
1231procedure TAcronymDb.LoadFromFile(FileName: string);
1232var
1233 NewNode: TDOMNode;
1234 Doc: TXMLDocument;
1235 RootNode: TDOMNode;
1236begin
1237 if ExtractFileExt(FileName) = '.csv' then begin
1238 LoadFromFileCSV(FileName);
1239 Exit;
1240 end;
1241 Self.FileName := FileName;
1242 ReadXMLFile(Doc, FileName);
1243 with Doc do try
1244 if Doc.DocumentElement.NodeName <> 'AcronymDecoderProject' then
1245 raise Exception.Create(SWrongFileFormat);
1246 RootNode := Doc.DocumentElement;
1247 with RootNode do begin
1248 NewNode := FindNode('Categories');
1249 if Assigned(NewNode) then
1250 Categories.LoadFromNode(NewNode);
1251
1252 // Load acronyms after categories because of references
1253 NewNode := FindNode('Acronyms');
1254 if Assigned(NewNode) then
1255 Acronyms.LoadFromNode(NewNode);
1256
1257 NewNode := FindNode('ImportFormats');
1258 if Assigned(NewNode) then
1259 ImportFormats.LoadFromNode(NewNode);
1260
1261 NewNode := FindNode('ImportSources');
1262 if Assigned(NewNode) then
1263 ImportSources.LoadFromNode(NewNode);
1264 end;
1265 finally
1266 Doc.Free;
1267 end;
1268end;
1269
1270procedure TAcronymDb.SaveToFile(FileName: string);
1271var
1272 NewNode: TDOMNode;
1273 Doc: TXMLDocument;
1274 RootNode: TDOMNode;
1275begin
1276 if ExtractFileExt(FileName) = '.csv' then begin
1277 SaveToFileCSV(FileName);
1278 Exit;
1279 end;
1280 Self.FileName := FileName;
1281 Doc := TXMLDocument.Create;
1282 with Doc do try
1283 RootNode := CreateElement('AcronymDecoderProject');
1284 AppendChild(RootNode);
1285 with RootNode do begin
1286 NewNode := OwnerDocument.CreateElement('Categories');
1287 AppendChild(NewNode);
1288 Categories.SaveToNode(NewNode);
1289
1290 // Save acronyms after categories because of references
1291 NewNode := OwnerDocument.CreateElement('Acronyms');
1292 AppendChild(NewNode);
1293 Acronyms.SaveToNode(NewNode);
1294
1295 NewNode := OwnerDocument.CreateElement('ImportFormats');
1296 AppendChild(NewNode);
1297 ImportFormats.SaveToNode(NewNode);
1298
1299 NewNode := OwnerDocument.CreateElement('ImportSources');
1300 AppendChild(NewNode);
1301 ImportSources.SaveToNode(NewNode);
1302 end;
1303 ForceDirectories(ExtractFileDir(FileName));
1304 WriteXMLFile(Doc, FileName);
1305 finally
1306 Doc.Free;
1307 end;
1308 Modified := False;
1309end;
1310
1311procedure TAcronymDb.LoadFromFileCSV(FileName: string);
1312var
1313 F: TStringList;
1314 Line: TStringList;
1315 CategoryStrings: TStringList;
1316 NewAcronym: TAcronym;
1317 NewMeaning: TAcronymMeaning;
1318 I: Integer;
1319 J: Integer;
1320 AcronymCategory: TAcronymCategory;
1321begin
1322 Self.FileName := FileName;
1323 Acronyms.Clear;
1324 F := TStringList.Create;
1325 Line := TStringList.Create;
1326 Line.StrictDelimiter := True;
1327 CategoryStrings := TStringList.Create;
1328 CategoryStrings.Delimiter := ';';
1329 try
1330 F.LoadFromFile(FileName);
1331 for I := 0 to F.Count - 1 do begin
1332 Line.CommaText := F[I];
1333 NewAcronym := Acronyms.SearchByName(Line[0]);
1334 if not Assigned(NewAcronym) then begin
1335 NewAcronym := TAcronym.Create;
1336 NewAcronym.Name := Line[0];
1337 Acronyms.Add(NewAcronym);
1338 end;
1339 NewMeaning := NewAcronym.Meanings.SearchByName(Line[1]);
1340 if not Assigned(NewMeaning) then begin
1341 NewMeaning := TAcronymMeaning.Create;
1342 NewMeaning.Name := Line[1];
1343 NewMeaning.Acronym := NewAcronym;
1344 NewAcronym.Meanings.Add(NewMeaning);
1345 end;
1346 CategoryStrings.DelimitedText := Line[2];
1347 for J := 0 to CategoryStrings.Count - 1 do begin
1348 AcronymCategory := Categories.SearchByName(CategoryStrings[J]);
1349 if not Assigned(AcronymCategory) then begin
1350 AcronymCategory := TAcronymCategory.Create;
1351 AcronymCategory.Name := CategoryStrings[J];
1352 Categories.Add(AcronymCategory);
1353 end;
1354 NewMeaning.Categories.Add(AcronymCategory);
1355 AcronymCategory.AcronymMeanings.Add(NewMeaning);
1356 end;
1357 end;
1358 finally
1359 F.Free;
1360 Line.Free;
1361 CategoryStrings.Free;
1362 end;
1363 Modified := False;
1364end;
1365
1366procedure TAcronymDb.SaveToFileCSV(FileName: string);
1367var
1368 I: Integer;
1369 J: Integer;
1370 K: Integer;
1371 F: TStringList;
1372 Line: TStringList;
1373 Context: TStringList;
1374begin
1375 Self.FileName := FileName;
1376 F := TStringList.Create;
1377 Line := TStringList.Create;
1378 Line.StrictDelimiter := True;
1379 Context := TStringList.Create;
1380 Context.Delimiter := ';';
1381 try
1382 Line.Clear;
1383 for I := 0 to Acronyms.Count - 1 do
1384 with TAcronym(Acronyms[I]) do begin
1385 for K := 0 to Meanings.Count - 1 do
1386 with TAcronymMeaning(Meanings[K]) do begin
1387 Line.Clear;
1388 Line.Add(Acronym.Name);
1389 Line.Add(Name);
1390 Context.Clear;
1391 for J := 0 to Categories.Count - 1 do
1392 Context.Add(TAcronymCategory(Categories[J]).Name);
1393 Line.Add(Context.DelimitedText);
1394 F.Add(Line.CommaText);
1395 end;
1396 end;
1397 F.SaveToFile(FileName);
1398 finally
1399 F.Free;
1400 Line.Free;
1401 Context.Free;
1402 end;
1403 Modified := False;
1404end;
1405
1406procedure TAcronymDb.FilterList(AName: string; Items: TAcronymMeanings);
1407var
1408 I: Integer;
1409 J: Integer;
1410begin
1411 AName := LowerCase(AName);
1412 Items.Clear;
1413 for I := 0 to Acronyms.Count - 1 do
1414 with TAcronym(Acronyms[I]) do begin
1415 for J := 0 to Meanings.Count - 1 do
1416 with TAcronymMeaning(Meanings[J]) do begin
1417 if (AName = '') or (Pos(AName, LowerCase(TAcronym(Acronyms[I]).Name)) > 0)
1418 or (Pos(AName, LowerCase(Name)) > 0) then Items.Add(TAcronymMeaning(Meanings[J]))
1419 end;
1420 end;
1421end;
1422
1423function TAcronymDb.AddAcronym(AcronymName, MeaningName: string): TAcronymMeaning;
1424var
1425 Acronym: TAcronym;
1426 Meaning: TAcronymMeaning;
1427begin
1428 Acronym := Acronyms.SearchByName(AcronymName);
1429 if not Assigned(Acronym) then begin
1430 Acronym := TAcronym.Create;
1431 Acronym.Name := AcronymName;
1432 Acronyms.Add(Acronym);
1433 end;
1434 Meaning := Acronym.Meanings.SearchByName(MeaningName);
1435 if not Assigned(Meaning) then begin
1436 Meaning := TAcronymMeaning.Create;
1437 Meaning.Name := MeaningName;
1438 Meaning.Acronym := Acronym;
1439 Acronym.Meanings.Add(Meaning);
1440 Inc(AddedCount);
1441 end;
1442 Result := Meaning;
1443 Modified := True;
1444end;
1445
1446procedure TAcronymDb.RemoveMeaning(Meaning: TAcronymMeaning);
1447var
1448 Acronym: TAcronym;
1449begin
1450 Acronym := Meaning.Acronym;
1451 Acronym.Meanings.Remove(Meaning);
1452 if Acronym.Meanings.Count = 0 then
1453 Acronyms.Remove(Acronym);
1454 Modified := True;
1455end;
1456
1457procedure TAcronymDb.RemoveAcronym(AcronymName, MeaningName: string);
1458var
1459 Acronym: TAcronym;
1460 Meaning: TAcronymMeaning;
1461begin
1462 Acronym := Acronyms.SearchByName(AcronymName);
1463 if Assigned(Acronym) then begin
1464 Meaning := Acronym.Meanings.SearchByName(MeaningName);
1465 if Assigned(Meaning) then RemoveMeaning(Meaning);
1466 end;
1467end;
1468
1469procedure TAcronymDb.AssignToList(List: TListObject);
1470var
1471 I: Integer;
1472 J: Integer;
1473begin
1474 List.Clear;
1475 for I := 0 to Acronyms.Count - 1 do
1476 with TAcronym(Acronyms[I]) do begin
1477 for J := 0 to Meanings.Count - 1 do
1478 with TAcronymMeaning(Meanings[J]) do begin
1479 List.Add(TAcronymMeaning(Meanings[J]))
1480 end;
1481 end;
1482end;
1483
1484end.
1485
Note: See TracBrowser for help on using the repository browser.