mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-05 11:18:18 +02:00
255 lines
7.2 KiB
ObjectPascal
255 lines
7.2 KiB
ObjectPascal
{
|
|
This file is part of the Free Component Library
|
|
Copyright (c) 2024 by Michael Van Canneyt michael@freepascal.org
|
|
|
|
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.
|
|
|