source: tags/1.2.0/UAcronym.pas

Last change on this file was 73, checked in by chronos, 8 years ago
  • Added: Text filtering in list of import sources.
  • Fixed: Now checkboxes in list of import sources are visible and working for enabling item.
File size: 39.6 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 Sources: TImportSources;
181 ItemCount: Integer;
182 LastImportTime: TDateTime;
183 Categories: TAcronymCategories;
184 UserName: string;
185 Password: string;
186 function DownloadHTTP(URL: string; Stream: TStream): Boolean;
187 procedure Process;
188 procedure ProcessTextParseURL;
189 procedure ProcessTextParseFile;
190 procedure ProcessMSAccess;
191 procedure Assign(Source: TImportSource);
192 procedure SaveToNode(Node: TDOMNode);
193 procedure LoadFromNode(Node: TDOMNode);
194 constructor Create;
195 destructor Destroy; override;
196 end;
197
198 { TImportSources }
199
200 TImportSources = class(TObjectList)
201 AcronymDb: TAcronymDb;
202 function SearchByName(Name: string): TImportSource;
203 procedure SaveToNode(Node: TDOMNode);
204 procedure LoadFromNode(Node: TDOMNode);
205 procedure AssignToList(List: TListObject);
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 J: Integer;
428 T: string;
429 LastLength: Integer;
430 AddedAcronym: TAcronymMeaning;
431begin
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 := StringReplace(T, '&lt;', '<', [rfReplaceAll]);
486 T := StringReplace(T, '&gt;', '>', [rfReplaceAll]);
487 T := Trim(T);
488 case Variable of
489 ivAcronym: NewAcronym.Name := T;
490 ivMeaning: NewAcronym.Meaning := T;
491 ivDescription: NewAcronym.Description := T;
492 end;
493 end;
494 Delete(S, 1, P + Length(EndString) - 1);
495
496 if (Flag = ipfNewItem) and (NewAcronym.Name <> '') and
497 (NewAcronym.Meaning <> '') then begin
498 AddedAcronym := Sources.AcronymDb.AddAcronym(NewAcronym.Name, NewAcronym.Meaning);
499 AddedAcronym.Description := NewAcronym.Description;
500
501 // Merge categories
502 for J := 0 to Categories.Count - 1 do
503 if AddedAcronym.Categories.IndexOf(Categories[J]) = -1 then begin
504 AddedAcronym.Categories.Add(Categories[J]);
505 TAcronymCategory(Categories[J]).AcronymMeanings.Add(AddedAcronym);
506 end;
507 Inc(ItemCount);
508 end;
509
510 if Repetition then begin
511 if Length(StartString) > 0 then begin
512 P1 := Pos(StartString, S);
513 if P1 > 0 then begin
514 P2 := Pos(TImportPattern(Format.ItemPatterns[(I + 1) mod Format.ItemPatterns.Count]).StartString, S);
515 if (P2 > 0) and (P1 < P2) then Continue;
516 end;
517 end;
518 end;
519 end;
520 end;
521 Inc(I);
522 end;
523 until Length(S) = LastLength;
524 finally
525 NewAcronym.Free;
526 end;
527end;
528
529
530function TImportSource.DownloadHTTP(URL: string; Stream: TStream): Boolean;
531var
532 HTTPClient: TFPHTTPClient;
533 FormData: TStringList;
534begin
535 Result := False;
536 HTTPClient := TFPHttpClient.Create(nil);
537 HTTPClient.AllowRedirect := True;
538 HTTPClient.OnPassword := DoPassword;
539 FormData := TStringList.Create;
540 try
541 HTTPClient.Get(URL, Stream);
542 Result := True;
543 finally
544 FormData.Free;
545 HTTPClient.Free;
546 end;
547end;
548
549procedure TImportSources.AssignToList(List: TListObject);
550var
551 I: Integer;
552begin
553 List.Clear;
554 for I := 0 to Count - 1 do
555 List.Add(TImportSource(Items[I]))
556end;
557
558procedure TImportSource.Process;
559begin
560 ItemCount := 0;
561 case Format.Kind of
562 ifkParseURL: ProcessTextParseURL;
563 ifkMSAccess: ProcessMSAccess;
564 ifkParseFile: ProcessTextParseFile;
565 else raise Exception.Create(SUnsupportedImportFormat);
566 end;
567 LastImportTime := Now;
568end;
569
570
571{ TImportFormat }
572
573procedure TImportFormat.Assign(Source: TImportFormat);
574var
575 I: Integer;
576begin
577 Kind := Source.Kind;
578 Name := Source.Name;
579 Block.StartString := Source.Block.StartString;
580 Block.EndString := Source.Block.EndString;
581 while ItemPatterns.Count < Source.ItemPatterns.Count do
582 ItemPatterns.Add(TImportPattern.Create);
583 if ItemPatterns.Count > Source.ItemPatterns.Count then
584 ItemPatterns.Count := Source.ItemPatterns.Count;
585 for I := 0 to ItemPatterns.Count - 1 do begin
586 TImportPattern(ItemPatterns[I]).Assign(TImportPattern(Source.ItemPatterns[I]));
587 end;
588end;
589
590procedure TImportFormat.SaveToNode(Node: TDOMNode);
591var
592 NewNode: TDOMNode;
593begin
594 WriteInteger(Node, 'Id', Id);
595 WriteString(Node, 'Name', Name);
596 WriteInteger(Node, 'Kind', Integer(Kind));
597 WriteString(Node, 'BlockStartString', Block.StartString);
598 WriteString(Node, 'BlockEndString', Block.EndString);
599
600 NewNode := Node.OwnerDocument.CreateElement('Patterns');
601 Node.AppendChild(NewNode);
602 ItemPatterns.SaveToNode(NewNode);
603end;
604
605procedure TImportFormat.LoadFromNode(Node: TDOMNode);
606var
607 NewNode: TDOMNode;
608begin
609 Id := ReadInteger(Node, 'Id', 0);
610 Name := ReadString(Node, 'Name', '');
611 Kind := TImportFormatKind(ReadInteger(Node, 'Kind', 0));
612 Block.StartString := ReadString(Node, 'BlockStartString', '');
613 Block.EndString := ReadString(Node, 'BlockEndString', '');
614
615 NewNode := Node.FindNode('Patterns');
616 if Assigned(NewNode) then
617 ItemPatterns.LoadFromNode(NewNode);
618end;
619
620constructor TImportFormat.Create;
621begin
622 Block := TImportPattern.Create;
623 ItemPatterns := TImportPatterns.Create;
624end;
625
626destructor TImportFormat.Destroy;
627begin
628 Block.Free;
629 ItemPatterns.Free;
630 inherited Destroy;
631end;
632
633{ TImportSources }
634
635function TImportSources.SearchByName(Name: string): TImportSource;
636var
637 I: Integer;
638begin
639 I := 0;
640 while (I < Count) and (TImportSource(Items[I]).Name <> Name) do Inc(I);
641 if I < Count then Result := TImportSource(Items[I])
642 else Result := nil;
643end;
644
645procedure TImportSources.SaveToNode(Node: TDOMNode);
646var
647 I: Integer;
648 NewNode2: TDOMNode;
649begin
650 for I := 0 to Count - 1 do
651 with TImportSource(Items[I]) do begin
652 NewNode2 := Node.OwnerDocument.CreateElement('ImportSource');
653 Node.AppendChild(NewNode2);
654 SaveToNode(NewNode2);
655 end;
656end;
657
658procedure TImportSources.LoadFromNode(Node: TDOMNode);
659var
660 Node2: TDOMNode;
661 NewItem: TImportSource;
662begin
663 Count := 0;
664 Node2 := Node.FirstChild;
665 while Assigned(Node2) and (Node2.NodeName = 'ImportSource') do begin
666 NewItem := TImportSource.Create;
667 NewItem.Sources := Self;
668 NewItem.LoadFromNode(Node2);
669 Add(NewItem);
670 Node2 := Node2.NextSibling;
671 end;
672end;
673
674{ TImportFormats }
675
676function TImportFormats.SearchByName(Name: string): TImportFormat;
677var
678 I: Integer;
679begin
680 I := 0;
681 while (I < Count) and (TImportFormat(Items[I]).Name <> Name) do Inc(I);
682 if I < Count then Result := TImportFormat(Items[I])
683 else Result := nil;
684end;
685
686procedure TImportFormats.UpdateIds;
687var
688 LastId: Integer;
689 I: Integer;
690begin
691 // Get highest used ID
692 LastId := 0;
693 for I := 0 to Count - 1 do begin
694 if TImportFormat(Items[I]).Id > LastId then LastId := TImportFormat(Items[I]).Id;
695 end;
696 // Add ID to new items without ID
697 for I := 0 to Count - 1 do begin
698 if TImportFormat(Items[I]).Id = 0 then begin
699 Inc(LastId);
700 TImportFormat(Items[I]).Id := LastId;
701 end;
702 end;
703end;
704
705procedure TImportFormats.SaveToNode(Node: TDOMNode);
706var
707 I: Integer;
708 NewNode2: TDOMNode;
709begin
710 UpdateIds;
711 for I := 0 to Count - 1 do
712 with TImportFormat(Items[I]) do begin
713 NewNode2 := Node.OwnerDocument.CreateElement('ImportFormat');
714 Node.AppendChild(NewNode2);
715 SaveToNode(NewNode2);
716 end;
717end;
718
719procedure TImportFormats.LoadFromNode(Node: TDOMNode);
720var
721 Node2: TDOMNode;
722 NewItem: TImportFormat;
723begin
724 Count := 0;
725 Node2 := Node.FirstChild;
726 while Assigned(Node2) and (Node2.NodeName = 'ImportFormat') do begin
727 NewItem := TImportFormat.Create;
728 NewItem.LoadFromNode(Node2);
729 Add(NewItem);
730 Node2 := Node2.NextSibling;
731 end;
732 UpdateIds;
733end;
734
735function TImportFormats.SearchById(Id: Integer): TImportFormat;
736var
737 I: Integer;
738begin
739 I := 0;
740 while (I < Count) and (TImportFormat(Items[I]).Id <> Id) do Inc(I);
741 if I < Count then Result := TImportFormat(Items[I])
742 else Result := nil;
743end;
744
745{ TImportSource }
746
747procedure TImportSource.ProcessTextParseURL;
748var
749 S: string;
750begin
751 ResponseStream.Clear;
752 if DownloadHTTP(URL, ResponseStream) then begin
753 ResponseStream.Position := 0;
754 SetLength(S, ResponseStream.Size);
755 ResponseStream.Read(S[1], Length(S));
756
757 TextParse(S);
758 end;
759end;
760
761procedure TImportSource.ProcessTextParseFile;
762var
763 S: TStringList;
764begin
765 if FileExists(URL) then begin
766 S := TStringList.Create;
767 try
768 S.LoadFromFile(URL);
769 TextParse(S.Text);
770 finally
771 S.Free;
772 end;
773 end else ShowMessage(SysUtils.Format(SFileNotFound, [URL]));
774end;
775
776procedure TImportSource.Assign(Source: TImportSource);
777begin
778 Enabled := Source.Enabled;
779 Name := Source.Name;
780 URL := Source.URL;
781 Format := Source.Format;
782 ItemCount := Source.ItemCount;
783 Categories.Assign(Source.Categories);
784 UserName := Source.UserName;
785 Password := Source.Password;
786 LastImportTime := Source.LastImportTime;
787end;
788
789procedure TImportSource.SaveToNode(Node: TDOMNode);
790var
791 NewNode: TDOMNode;
792begin
793 WriteString(Node, 'Name', Name);
794 WriteString(Node, 'URL', URL);
795 if Assigned(Format) then WriteInteger(Node, 'ImportFormat', Format.Id)
796 else WriteInteger(Node, 'ImportFormat', -1);
797 WriteBoolean(Node, 'Enabled', Enabled);
798 WriteInteger(Node, 'ItemCount', ItemCount);
799 WriteDateTime(Node, 'LastImportTime', LastImportTime);
800 WriteString(Node, 'UserName', UserName);
801
802 NewNode := Node.OwnerDocument.CreateElement('Categories');
803 Node.AppendChild(NewNode);
804 Categories.SaveRefToNode(NewNode);
805end;
806
807procedure TImportSource.LoadFromNode(Node: TDOMNode);
808var
809 Node2: TDOMNode;
810begin
811 Name := ReadString(Node, 'Name', '');
812 URL := ReadString(Node, 'URL', '');
813 Format := Sources.AcronymDb.ImportFormats.SearchById(ReadInteger(Node, 'ImportFormat', -1));
814 Enabled := ReadBoolean(Node, 'Enabled', True);
815 ItemCount := ReadInteger(Node, 'ItemCount', 0);
816 UserName := ReadString(Node, 'UserName', '');
817 LastImportTime := ReadDateTime(Node, 'LastImportTime', 0);
818
819 Categories.Db := Sources.AcronymDb;
820 Node2 := Node.FindNode('Categories');
821 if Assigned(Node2) then
822 Categories.LoadRefFromNode(Node2);
823end;
824
825constructor TImportSource.Create;
826begin
827 Format := nil;
828 Enabled := True;
829 Categories := TAcronymCategories.Create;
830 Categories.OwnsObjects := False;
831 ResponseStream := TMemoryStream.Create;
832end;
833
834destructor TImportSource.Destroy;
835begin
836 FreeAndNil(ResponseStream);
837 FreeAndNil(Categories);
838 inherited Destroy;
839end;
840
841{ TAcronymEntry }
842
843constructor TAcronymEntry.Create;
844begin
845 Categories := TStringList.Create;
846 Name := '';
847 Meaning := '';
848 Description := '';
849end;
850
851destructor TAcronymEntry.Destroy;
852begin
853 FreeAndNil(Categories);
854 inherited Destroy;
855end;
856
857{ TAcronymMeanings }
858
859procedure TAcronymMeanings.UpdateIds;
860var
861 LastId: Integer;
862 I: Integer;
863begin
864 // Get highest used ID
865 LastId := 0;
866 for I := 0 to Count - 1 do begin
867 if TAcronymMeaning(Items[I]).Id > LastId then LastId := TAcronymMeaning(Items[I]).Id;
868 end;
869 // Add ID to new items without ID
870 for I := 0 to Count - 1 do begin
871 if TAcronymMeaning(Items[I]).Id = 0 then begin
872 Inc(LastId);
873 TAcronymMeaning(Items[I]).Id := LastId;
874 end;
875 end;
876end;
877
878procedure TAcronymMeanings.SaveToNode(Node: TDOMNode);
879var
880 I: Integer;
881 NewNode2: TDOMNode;
882begin
883 UpdateIds;
884 for I := 0 to Count - 1 do
885 with TAcronymMeaning(Items[I]) do begin
886 NewNode2 := Node.OwnerDocument.CreateElement('Meaning');
887 Node.AppendChild(NewNode2);
888 SaveToNode(NewNode2);
889 end;
890end;
891
892procedure TAcronymMeanings.LoadFromNode(Node: TDOMNode);
893var
894 Node2: TDOMNode;
895 NewItem: TAcronymMeaning;
896begin
897 Count := 0;
898 Node2 := Node.FirstChild;
899 while Assigned(Node2) and (Node2.NodeName = 'Meaning') do begin
900 NewItem := TAcronymMeaning.Create;
901 NewItem.Acronym := Acronym;
902 NewItem.LoadFromNode(Node2);
903 Add(NewItem);
904 Node2 := Node2.NextSibling;
905 end;
906 UpdateIds;
907end;
908
909function TAcronymMeanings.SearchByName(Name: string): TAcronymMeaning;
910var
911 I: Integer;
912begin
913 I := 0;
914 while (I < Count) and (TAcronymMeaning(Items[I]).Name <> Name) do Inc(I);
915 if I < Count then Result := TAcronymMeaning(Items[I])
916 else Result := nil;
917end;
918
919function TAcronymMeanings.AddMeaning(Name: string): TAcronymMeaning;
920begin
921 Result := TAcronymMeaning.Create;
922 Result.Name := Name;
923 Add(Result);
924end;
925
926{ TAcronymMeaning }
927
928procedure TAcronymMeaning.SaveToNode(Node: TDOMNode);
929var
930 NewNode: TDOMNode;
931begin
932 WriteString(Node, 'Name', Name);
933 WriteString(Node, 'Description', Description);
934 WriteString(Node, 'Language', Language);
935
936 NewNode := Node.OwnerDocument.CreateElement('Categories');
937 Node.AppendChild(NewNode);
938 Categories.SaveRefToNode(NewNode);
939end;
940
941procedure TAcronymMeaning.LoadFromNode(Node: TDOMNode);
942var
943 Node2: TDOMNode;
944 I: Integer;
945begin
946 Name := ReadString(Node, 'Name', '');
947 Description := ReadString(Node, 'Description', '');
948 Language := ReadString(Node, 'Language', '');
949
950 Categories.Db := Acronym.Db;
951 Node2 := Node.FindNode('Categories');
952 if Assigned(Node2) then begin
953 Categories.LoadRefFromNode(Node2);
954
955 // Add reverse references
956 for I := 0 to Categories.Count - 1 do
957 TAcronymCategory(Categories[I]).AcronymMeanings.Add(Self);
958 end;
959end;
960
961constructor TAcronymMeaning.Create;
962begin
963 Categories := TAcronymCategories.Create(False);
964end;
965
966destructor TAcronymMeaning.Destroy;
967var
968 I: Integer;
969begin
970 for I := 0 to Categories.Count - 1 do
971 TAcronymCategory(Categories[I]).AcronymMeanings.Remove(Self);
972 FreeAndNil(Categories);
973 inherited Destroy;
974end;
975
976{ TAcronyms }
977
978procedure TAcronyms.SaveToNode(Node: TDOMNode);
979var
980 I: Integer;
981 NewNode2: TDOMNode;
982begin
983 for I := 0 to Count - 1 do
984 with TAcronym(Items[I]) do begin
985 NewNode2 := Node.OwnerDocument.CreateElement('Acronym');
986 Node.AppendChild(NewNode2);
987 SaveToNode(NewNode2);
988 end;
989end;
990
991procedure TAcronyms.LoadFromNode(Node: TDOMNode);
992var
993 Node2: TDOMNode;
994 NewItem: TAcronym;
995begin
996 Count := 0;
997 Node2 := Node.FirstChild;
998 while Assigned(Node2) and (Node2.NodeName = 'Acronym') do begin
999 NewItem := TAcronym.Create;
1000 NewItem.Db := Db;
1001 NewItem.LoadFromNode(Node2);
1002 Add(NewItem);
1003 Node2 := Node2.NextSibling;
1004 end;
1005end;
1006
1007function TAcronyms.SearchByName(Name: string): TAcronym;
1008var
1009 I: Integer;
1010begin
1011 I := 0;
1012 while (I < Count) and (TAcronym(Items[I]).Name <> Name) do Inc(I);
1013 if I < Count then Result := TAcronym(Items[I])
1014 else Result := nil;
1015end;
1016
1017function TAcronyms.AddAcronym(Name: string): TAcronym;
1018begin
1019 Result := TAcronym.Create;
1020 Result.Name := Name;
1021 Add(Result);
1022end;
1023
1024{ TAcronymCategories }
1025
1026procedure TAcronymCategories.UpdateIds;
1027var
1028 LastId: Integer;
1029 I: Integer;
1030begin
1031 // Get highest used ID
1032 LastId := 0;
1033 for I := 0 to Count - 1 do begin
1034 if TAcronymCategory(Items[I]).Id > LastId then LastId := TAcronymCategory(Items[I]).Id;
1035 end;
1036 // Add ID to new items without ID
1037 for I := 0 to Count - 1 do begin
1038 if TAcronymCategory(Items[I]).Id = 0 then begin
1039 Inc(LastId);
1040 TAcronymCategory(Items[I]).Id := LastId;
1041 end;
1042 end;
1043end;
1044
1045procedure TAcronymCategories.SaveToNode(Node: TDOMNode);
1046var
1047 I: Integer;
1048 NewNode2: TDOMNode;
1049begin
1050 UpdateIds;
1051 for I := 0 to Count - 1 do
1052 with TAcronymCategory(Items[I]) do begin
1053 NewNode2 := Node.OwnerDocument.CreateElement('Category');
1054 Node.AppendChild(NewNode2);
1055 SaveToNode(NewNode2);
1056 end;
1057end;
1058
1059procedure TAcronymCategories.LoadFromNode(Node: TDOMNode);
1060var
1061 Node2: TDOMNode;
1062 NewItem: TAcronymCategory;
1063begin
1064 Count := 0;
1065 Node2 := Node.FirstChild;
1066 while Assigned(Node2) and (Node2.NodeName = 'Category') do begin
1067 NewItem := TAcronymCategory.Create;
1068 NewItem.LoadFromNode(Node2);
1069 Add(NewItem);
1070 Node2 := Node2.NextSibling;
1071 end;
1072 UpdateIds;
1073end;
1074
1075procedure TAcronymCategories.SaveRefToNode(Node: TDOMNode);
1076var
1077 I: Integer;
1078 NewNode: TDOMNode;
1079begin
1080 for I := 0 to Count - 1 do begin
1081 NewNode := Node.OwnerDocument.CreateElement('Category');
1082 Node.AppendChild(NewNode);
1083 WriteInteger(NewNode, 'Id', TAcronymCategory(Items[I]).Id);
1084 end;
1085end;
1086
1087procedure TAcronymCategories.LoadRefFromNode(Node: TDOMNode);
1088var
1089 Node2: TDOMNode;
1090 Id: Integer;
1091 Category: TAcronymCategory;
1092begin
1093 Node2 := Node.FirstChild;
1094 while Assigned(Node2) and (Node2.NodeName = 'Category') do begin
1095 Id := ReadInteger(Node2, 'Id', 0);
1096 Category := Db.Categories.SearchById(Id);
1097 if Assigned(Category) then begin
1098 Add(Category);
1099 end;
1100 Node2 := Node2.NextSibling;
1101 end;
1102end;
1103
1104function TAcronymCategories.SearchByName(Name: string): TAcronymCategory;
1105var
1106 I: Integer;
1107begin
1108 I := 0;
1109 while (I < Count) and (TAcronymCategory(Items[I]).Name <> Name) do Inc(I);
1110 if I < Count then Result := TAcronymCategory(Items[I])
1111 else Result := nil;
1112end;
1113
1114function TAcronymCategories.SearchById(Id: Integer): TAcronymCategory;
1115var
1116 I: Integer;
1117begin
1118 I := 0;
1119 while (I < Count) and (TAcronymCategory(Items[I]).Id <> Id) do Inc(I);
1120 if I < Count then Result := TAcronymCategory(Items[I])
1121 else Result := nil;
1122end;
1123
1124function TAcronymCategories.AddContext(Name: string): TAcronymCategory;
1125begin
1126 Result := TAcronymCategory.Create;
1127 Result.Name := Name;
1128 Add(Result);
1129end;
1130
1131procedure TAcronymCategories.AssignToStrings(Strings: TStrings);
1132var
1133 I: Integer;
1134begin
1135 Strings.Clear;
1136 for I := 0 to Count - 1 do
1137 Strings.AddObject(TAcronymCategory(Items[I]).Name, Items[I]);
1138end;
1139
1140procedure TAcronymCategories.AssignFromStrings(Strings: TStrings);
1141var
1142 I: Integer;
1143begin
1144 Clear;
1145 for I := 0 to Strings.Count - 1 do begin
1146 Add(TAcronymCategory(Strings.Objects[I]));
1147 end;
1148end;
1149
1150function TAcronymCategories.GetString: string;
1151var
1152 I: Integer;
1153begin
1154 Result := '';
1155 for I := 0 to Count - 1 do
1156 Result := Result + TAcronymCategory(Items[I]).Name + ',';
1157 System.Delete(Result, Length(Result), 1);
1158end;
1159
1160
1161{ TAcronym }
1162
1163procedure TAcronym.SaveToNode(Node: TDOMNode);
1164var
1165 NewNode: TDOMNode;
1166begin
1167 WriteString(Node, 'Name', Name);
1168
1169 NewNode := Node.OwnerDocument.CreateElement('Meanings');
1170 Node.AppendChild(NewNode);
1171 Meanings.SaveToNode(NewNode);
1172end;
1173
1174procedure TAcronym.LoadFromNode(Node: TDOMNode);
1175var
1176 NewNode: TDOMNode;
1177begin
1178 Name := ReadString(Node, 'Name', '');
1179
1180 NewNode := Node.FindNode('Meanings');
1181 if Assigned(NewNode) then
1182 Meanings.LoadFromNode(NewNode);
1183end;
1184
1185constructor TAcronym.Create;
1186begin
1187 Meanings := TAcronymMeanings.Create;
1188 Meanings.Acronym := Self;
1189end;
1190
1191destructor TAcronym.Destroy;
1192begin
1193 FreeAndNil(Meanings);
1194 inherited Destroy;
1195end;
1196
1197{ TAcronymCategory }
1198
1199procedure TAcronymCategory.SaveToNode(Node: TDOMNode);
1200begin
1201 WriteString(Node, 'Name', Name);
1202 WriteInteger(Node, 'Id', Id);
1203end;
1204
1205procedure TAcronymCategory.LoadFromNode(Node: TDOMNode);
1206begin
1207 Name := ReadString(Node, 'Name', '');
1208 Id := ReadInteger(Node, 'Id', 0);
1209end;
1210
1211constructor TAcronymCategory.Create;
1212begin
1213 AcronymMeanings := TAcronymMeanings.Create(False);
1214end;
1215
1216destructor TAcronymCategory.Destroy;
1217var
1218 I: Integer;
1219begin
1220 for I := 0 to AcronymMeanings.Count - 1 do
1221 TAcronymMeaning(AcronymMeanings[I]).Categories.Remove(Self);
1222 FreeAndNil(AcronymMeanings);
1223 inherited Destroy;
1224end;
1225
1226{ TAcronymDb }
1227
1228constructor TAcronymDb.Create;
1229begin
1230 Sources := TAcronymSources.Create;
1231 Acronyms := TAcronyms.Create;
1232 Acronyms.Db := Self;
1233 Categories := TAcronymCategories.Create;
1234 ImportSources := TImportSources.Create;
1235 ImportSources.AcronymDb := Self;
1236 ImportFormats := TImportFormats.Create;
1237end;
1238
1239destructor TAcronymDb.Destroy;
1240begin
1241 FreeAndNil(ImportFormats);
1242 FreeAndNil(ImportSources);
1243 FreeAndNil(Sources);
1244 FreeAndNil(Acronyms);
1245 FreeAndNil(Categories);
1246 inherited Destroy;
1247end;
1248
1249procedure TAcronymDb.LoadFromFile(FileName: string);
1250var
1251 NewNode: TDOMNode;
1252 Doc: TXMLDocument;
1253 RootNode: TDOMNode;
1254begin
1255 if ExtractFileExt(FileName) = '.csv' then begin
1256 LoadFromFileCSV(FileName);
1257 Exit;
1258 end;
1259 Self.FileName := FileName;
1260 ReadXMLFile(Doc, FileName);
1261 with Doc do try
1262 if Doc.DocumentElement.NodeName <> 'AcronymDecoderProject' then
1263 raise Exception.Create(SWrongFileFormat);
1264 RootNode := Doc.DocumentElement;
1265 with RootNode do begin
1266 NewNode := FindNode('Categories');
1267 if Assigned(NewNode) then
1268 Categories.LoadFromNode(NewNode);
1269
1270 // Load acronyms after categories because of references
1271 NewNode := FindNode('Acronyms');
1272 if Assigned(NewNode) then
1273 Acronyms.LoadFromNode(NewNode);
1274
1275 NewNode := FindNode('ImportFormats');
1276 if Assigned(NewNode) then
1277 ImportFormats.LoadFromNode(NewNode);
1278
1279 NewNode := FindNode('ImportSources');
1280 if Assigned(NewNode) then
1281 ImportSources.LoadFromNode(NewNode);
1282 end;
1283 finally
1284 Doc.Free;
1285 end;
1286end;
1287
1288procedure TAcronymDb.SaveToFile(FileName: string);
1289var
1290 NewNode: TDOMNode;
1291 Doc: TXMLDocument;
1292 RootNode: TDOMNode;
1293begin
1294 if ExtractFileExt(FileName) = '.csv' then begin
1295 SaveToFileCSV(FileName);
1296 Exit;
1297 end;
1298 Self.FileName := FileName;
1299 Doc := TXMLDocument.Create;
1300 with Doc do try
1301 RootNode := CreateElement('AcronymDecoderProject');
1302 AppendChild(RootNode);
1303 with RootNode do begin
1304 NewNode := OwnerDocument.CreateElement('Categories');
1305 AppendChild(NewNode);
1306 Categories.SaveToNode(NewNode);
1307
1308 // Save acronyms after categories because of references
1309 NewNode := OwnerDocument.CreateElement('Acronyms');
1310 AppendChild(NewNode);
1311 Acronyms.SaveToNode(NewNode);
1312
1313 NewNode := OwnerDocument.CreateElement('ImportFormats');
1314 AppendChild(NewNode);
1315 ImportFormats.SaveToNode(NewNode);
1316
1317 NewNode := OwnerDocument.CreateElement('ImportSources');
1318 AppendChild(NewNode);
1319 ImportSources.SaveToNode(NewNode);
1320 end;
1321 ForceDirectories(ExtractFileDir(FileName));
1322 WriteXMLFile(Doc, FileName);
1323 finally
1324 Doc.Free;
1325 end;
1326 Modified := False;
1327end;
1328
1329procedure TAcronymDb.LoadFromFileCSV(FileName: string);
1330var
1331 F: TStringList;
1332 Line: TStringList;
1333 CategoryStrings: TStringList;
1334 NewAcronym: TAcronym;
1335 NewMeaning: TAcronymMeaning;
1336 I: Integer;
1337 J: Integer;
1338 AcronymCategory: TAcronymCategory;
1339begin
1340 Self.FileName := FileName;
1341 Acronyms.Clear;
1342 F := TStringList.Create;
1343 Line := TStringList.Create;
1344 Line.StrictDelimiter := True;
1345 CategoryStrings := TStringList.Create;
1346 CategoryStrings.Delimiter := ';';
1347 try
1348 F.LoadFromFile(FileName);
1349 for I := 0 to F.Count - 1 do begin
1350 Line.CommaText := F[I];
1351 NewAcronym := Acronyms.SearchByName(Line[0]);
1352 if not Assigned(NewAcronym) then begin
1353 NewAcronym := TAcronym.Create;
1354 NewAcronym.Name := Line[0];
1355 Acronyms.Add(NewAcronym);
1356 end;
1357 NewMeaning := NewAcronym.Meanings.SearchByName(Line[1]);
1358 if not Assigned(NewMeaning) then begin
1359 NewMeaning := TAcronymMeaning.Create;
1360 NewMeaning.Name := Line[1];
1361 NewMeaning.Acronym := NewAcronym;
1362 NewAcronym.Meanings.Add(NewMeaning);
1363 end;
1364 CategoryStrings.DelimitedText := Line[2];
1365 for J := 0 to CategoryStrings.Count - 1 do begin
1366 AcronymCategory := Categories.SearchByName(CategoryStrings[J]);
1367 if not Assigned(AcronymCategory) then begin
1368 AcronymCategory := TAcronymCategory.Create;
1369 AcronymCategory.Name := CategoryStrings[J];
1370 Categories.Add(AcronymCategory);
1371 end;
1372 NewMeaning.Categories.Add(AcronymCategory);
1373 AcronymCategory.AcronymMeanings.Add(NewMeaning);
1374 end;
1375 end;
1376 finally
1377 F.Free;
1378 Line.Free;
1379 CategoryStrings.Free;
1380 end;
1381 Modified := False;
1382end;
1383
1384procedure TAcronymDb.SaveToFileCSV(FileName: string);
1385var
1386 I: Integer;
1387 J: Integer;
1388 K: Integer;
1389 F: TStringList;
1390 Line: TStringList;
1391 Context: TStringList;
1392begin
1393 Self.FileName := FileName;
1394 F := TStringList.Create;
1395 Line := TStringList.Create;
1396 Line.StrictDelimiter := True;
1397 Context := TStringList.Create;
1398 Context.Delimiter := ';';
1399 try
1400 Line.Clear;
1401 for I := 0 to Acronyms.Count - 1 do
1402 with TAcronym(Acronyms[I]) do begin
1403 for K := 0 to Meanings.Count - 1 do
1404 with TAcronymMeaning(Meanings[K]) do begin
1405 Line.Clear;
1406 Line.Add(Acronym.Name);
1407 Line.Add(Name);
1408 Context.Clear;
1409 for J := 0 to Categories.Count - 1 do
1410 Context.Add(TAcronymCategory(Categories[J]).Name);
1411 Line.Add(Context.DelimitedText);
1412 F.Add(Line.CommaText);
1413 end;
1414 end;
1415 F.SaveToFile(FileName);
1416 finally
1417 F.Free;
1418 Line.Free;
1419 Context.Free;
1420 end;
1421 Modified := False;
1422end;
1423
1424procedure TAcronymDb.FilterList(AName: string; Items: TAcronymMeanings);
1425var
1426 I: Integer;
1427 J: Integer;
1428begin
1429 AName := LowerCase(AName);
1430 Items.Clear;
1431 for I := 0 to Acronyms.Count - 1 do
1432 with TAcronym(Acronyms[I]) do begin
1433 for J := 0 to Meanings.Count - 1 do
1434 with TAcronymMeaning(Meanings[J]) do begin
1435 if (AName = '') or (Pos(AName, LowerCase(TAcronym(Acronyms[I]).Name)) > 0)
1436 or (Pos(AName, LowerCase(Name)) > 0) then Items.Add(TAcronymMeaning(Meanings[J]))
1437 end;
1438 end;
1439end;
1440
1441function TAcronymDb.AddAcronym(AcronymName, MeaningName: string): TAcronymMeaning;
1442var
1443 Acronym: TAcronym;
1444 Meaning: TAcronymMeaning;
1445begin
1446 Acronym := Acronyms.SearchByName(AcronymName);
1447 if not Assigned(Acronym) then begin
1448 Acronym := TAcronym.Create;
1449 Acronym.Name := AcronymName;
1450 Acronyms.Add(Acronym);
1451 end;
1452 Meaning := Acronym.Meanings.SearchByName(MeaningName);
1453 if not Assigned(Meaning) then begin
1454 Meaning := TAcronymMeaning.Create;
1455 Meaning.Name := MeaningName;
1456 Meaning.Acronym := Acronym;
1457 Acronym.Meanings.Add(Meaning);
1458 Inc(AddedCount);
1459 end;
1460 Result := Meaning;
1461 Modified := True;
1462end;
1463
1464procedure TAcronymDb.RemoveMeaning(Meaning: TAcronymMeaning);
1465var
1466 Acronym: TAcronym;
1467begin
1468 Acronym := Meaning.Acronym;
1469 Acronym.Meanings.Remove(Meaning);
1470 if Acronym.Meanings.Count = 0 then
1471 Acronyms.Remove(Acronym);
1472 Modified := True;
1473end;
1474
1475procedure TAcronymDb.RemoveAcronym(AcronymName, MeaningName: string);
1476var
1477 Acronym: TAcronym;
1478 Meaning: TAcronymMeaning;
1479begin
1480 Acronym := Acronyms.SearchByName(AcronymName);
1481 if Assigned(Acronym) then begin
1482 Meaning := Acronym.Meanings.SearchByName(MeaningName);
1483 if Assigned(Meaning) then RemoveMeaning(Meaning);
1484 end;
1485end;
1486
1487procedure TAcronymDb.AssignToList(List: TListObject);
1488var
1489 I: Integer;
1490 J: Integer;
1491begin
1492 List.Clear;
1493 for I := 0 to Acronyms.Count - 1 do
1494 with TAcronym(Acronyms[I]) do begin
1495 for J := 0 to Meanings.Count - 1 do
1496 with TAcronymMeaning(Meanings[J]) do begin
1497 List.Add(TAcronymMeaning(Meanings[J]))
1498 end;
1499 end;
1500end;
1501
1502end.
1503
Note: See TracBrowser for help on using the repository browser.