source: tags/1.3.1/UAcronym.pas

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