123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254 |
- {
- This file is part of the Free Component Library
- Copyright (c) 2024 by Michael Van Canneyt [email protected]
- Open API to pascal code generator
- See the file COPYING.FPC, included in this distribution,
- for details about the copyright.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- **********************************************************************}
- program openapi2pas;
- {$mode objfpc}{$H+}
- uses
- Classes,
- SysUtils,
- CustApp,
- fpjson,
- fpyaml.parser,
- fpyaml.data,
- fpyaml.json,
- fpopenapi.objects,
- fpopenapi.reader,
- fpopenapi.codegen;
- type
- { TGenDTOApplication }
- TGenDTOApplication = class(TCustomApplication)
- private
- FInputIsYAML : Boolean;
- FQuiet : Boolean;
- FCodeGen : TOpenAPICodeGen;
- FServiceMapFile,
- FUUIDMapFile : String;
- procedure ReadYAML(const aInputFile: string; aApi: TOpenAPI);
- protected
- Procedure DoLog(EventType : TEventType; const Msg : String); override;
- procedure DoRun; override;
- procedure ReadOpenAPi(const aInputFile: string; aApi: TOpenAPI);
- procedure WriteAPI(aApi: TOpenAPI; const aOutputFile: String);
- procedure WriteConfig(const aFileName: string);
- public
- constructor Create(TheOwner: TComponent); override;
- destructor Destroy; override;
- procedure Usage(const aMessage : string); virtual;
- end;
- { TGenDTOApplication }
- procedure TGenDTOApplication.WriteAPI(aApi: TOpenAPI; const aOutputFile : String) ;
- begin
- FCodeGen.OnLog:=@DoLog;
- FCodeGen.BaseOutputFileName:=aOutputFile;
- FCodeGen.API:=aAPI;
- if (FUUIDMapFile<>'') and FileExists(FUUIDMapFile) then
- FCodeGen.UUIDMap.LoadFromFile(FUUIDMapFile);
- if (FServiceMapFile<>'') then
- FCodeGen.ServiceMap.LoadFromFile(FServiceMapFile);
- FCodeGen.Execute;
- if FUUIDMapFile<>'' then
- FCodeGen.UUIDMap.SavetoFile(FUUIDMapFile);
- end;
- procedure TGenDTOApplication.ReadYAML(const aInputFile : string; aApi: TOpenAPI);
- var
- lParser : TYAMLParser;
- lYAML : TYAMLStream;
- lJSON : TJSONData;
- lJSONString : TJSONStringType;
- lReader : TOpenAPIReader;
- begin
- lYAML:=Nil;
- lParser:=TYAMLParser.Create(aInputFile);
- try
- lYAML:=lParser.Parse;
- finally
- lParser.Free;
- end;
- lJSON:=Nil;
- try
- lJSON:=YAMLtoJSON(lYAML);
- lJSONString:=lJSON.FormatJSON();
- finally
- lJSON.Free;
- end;
- lReader:=TOpenAPIReader.Create(Self);
- try
- lReader.ReadFromString(aAPI,lJSONString);
- finally
- lReader.Free;
- end;
- end;
- procedure TGenDTOApplication.ReadOpenAPi(const aInputFile : string; aApi: TOpenAPI);
- var
- lReader : TOpenAPIReader;
- begin
- lReader:=TOpenAPIReader.Create(Self);
- try
- lReader.ReadFromFile(aAPI,aInputFile);
- finally
- lReader.Free;
- end;
- end;
- procedure TGenDTOApplication.DoLog(EventType: TEventType; const Msg: String);
- begin
- if FQuiet then
- exit;
- Writeln(EventType,' : ',Msg);
- end;
- procedure TGenDTOApplication.WriteConfig(const aFileName : string);
- var
- lDir : String;
- begin
- lDir:=ExtractFilePath(aFileName);
- if lDir<>'' then
- If not ForceDirectories(lDir) then
- begin
- Writeln(StdErr,'Failed to create directory ',lDir);
- Exit;
- end;
- Log(etInfo,'Writing config file to %s',[aFileName]);
- FCodegen.SaveConfig(aFileName);
- end;
- procedure TGenDTOApplication.DoRun;
- const
- shortOpts = 'hi:o:dequ:s:varcC:bnw:y';
- LongOpts : Array of string = ('help','input:','output:','delphi','uuid-map:','quiet','service-map','verbose-header','enumerated','async','server','client','config:','abstract','no-implementation','write-config:','yaml');
- var
- lAPI : TOpenAPI;
- lConfig, lOutputFile,lInputFile, ErrorMsg : String;
- begin
- Terminate;
- ErrorMsg:=CheckOptions(ShortOPts,LongOpts);
- if (ErrorMsg<>'') or HasOption('h','help') then
- begin
- Usage(ErrorMsg);
- Exit;
- end;
- lConfig:=GetOptionValue('C','config');
- if (lConfig<>'') then
- FCodeGen.LoadConfig(lConfig);
- FCodeGen.DelphiCode:=HasOption('d','delphi');
- FCodeGen.VerboseHeader:=HasOption('v','verbose-header');
- FCodeGen.UseEnums:=HasOption('e','enumerated');
- FCodeGen.AsyncService:=HasOption('a','async');
- lInputFile:=GetOptionValue('i','input');
- lOutputFile:=GetOptionValue('o','output');
- FUUIDMapFile:=GetOptionValue('u','uuid-map');
- FServiceMapFile:=GetOptionValue('s','service-map');
- FCodeGen.GenerateServer:=HasOption('r','server');
- FCodeGen.GenerateClient:=HasOption('c','client');
- FCodeGen.AbstractServiceCalls:=HasOption('b','abstract');
- FCodeGen.SkipServerServiceImplementationModule:=HasOption('n','no-implementation');
- FInputIsYAML:=HasOption('y','yaml') or TYAMLParser.IsYamlFileName(lInputFile);
- FQuiet:=HasOption('q','quiet');
- if HasOption('w','write-config') then
- WriteConfig(GetOptionValue('w','write-config'))
- else
- begin
- if lInputFile='' then
- begin
- Usage('No input file specified.');
- Exit;
- end;
- if lOutputFile='' then
- lOutputFile:=ChangeFileExt(lInputFile,'');
- lAPI:=TOpenAPI.Create;
- try
- if FInputIsYAML then
- ReadYAML(lInputFile,lAPI)
- else
- ReadOpenAPi(lInputFile,lAPI);
- WriteApi(lApi,lOutputFile);
- finally
- lApi.Free;
- end;
- end;
- end;
- constructor TGenDTOApplication.Create(TheOwner: TComponent);
- begin
- inherited Create(TheOwner);
- ExceptionExitCode:=1;
- StopOnException:=True;
- FCodeGen:=TOpenAPICodeGen.Create(Self);
- end;
- destructor TGenDTOApplication.Destroy;
- begin
- FreeAndNil(FCodeGen);
- inherited Destroy;
- end;
- procedure TGenDTOApplication.Usage(const aMessage: string);
- begin
- if aMessage<>'' then
- Writeln('Error : ',aMessage);
- writeln('Usage: ', ExtractFileName(ExeName), ' [options]');
- Writeln('Where options is one or more of:');
- Writeln('-a --async Generate asynchronous service calls.');
- Writeln('-b --abstract Split server in abstract handler and implementation modules (and units).');
- Writeln('-c --client Generate client-side service.');
- Writeln('-C --config=FILE Read config file with converter settings.');
- Writeln('-d --delphi Generate delphi code for DTO/Serializer/Service definitions.');
- Writeln('-e --enumerated Use enumerateds (default is to keep strings).');
- Writeln('-h --help This message.');
- Writeln('-i --input=FILE OpenAPI JSON File to use. Required.');
- Writeln('-n --no-implementation Skip generation of server service module (only useful when -b is used).');
- Writeln('-o --output=FILE Base filename for output.');
- Writeln('-q --quiet Be less verbose.');
- Writeln('-r --server Generate a HTTP server module.');
- Writeln('-s --service-map=FILE Read service and method name mapping from file.');
- Writeln('-u --uuid-map=FILE Read (and write) a file with UUIDs for interfaces.');
- Writeln('-v --verbose-header Add OpenAPI description to unit header.');
- Writeln('-w --write-config=FILE Write a configuration file with current settings and exit.');
- ExitCode:=Ord(aMessage<>'');
- end;
- var
- Application: TGenDTOApplication;
- begin
- Application:=TGenDTOApplication.Create(nil);
- Application.Title:='Generate DTO Application';
- Application.Run;
- Application.Free;
- end.
|