lazarus-ccr/wst/trunk/ws_helper/generatorj.pas
2016-05-11 17:14:23 +00:00

621 lines
17 KiB
ObjectPascal

{
This file is part of the Web Service Toolkit
Copyright (c) 2015 by Inoussa OUEDRAOGO
This file is provide under modified LGPL licence
( the files COPYING.modifiedLGPL and COPYING.LGPL).
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.
}
{$INCLUDE wst_global.inc}
unit generatorj;
interface
uses
Classes, SysUtils,
PasTree,
pascal_parser_intf, source_utils, wst_types, generatorbase;
type
{ TInftGenerator }
TInftGenerator = class(TBaseGenerator)
private
FStream : ISourceStream;
private
function GenerateIntfName(AIntf : TPasElement):string;
function GenerateTypeText(AType : TPasType) : string;
procedure GenerateIntfProcParamsTypes(AProc : TPasProcedure);
procedure GenerateIntf(AIntf : TPasClassType);
procedure GenerateIntfProxy(AIntf : TPasClassType);
procedure GenerateClass(ASymbol : TPasClassType);
procedure GenerateEnum(ASymbol : TPasEnumType);
function GetDestUnitName():string;
procedure GenerateEnums();
procedure PrepareModule();
procedure InternalExecute();
public
procedure Execute();override;
end;
implementation
uses
contnrs,
parserutils, logger_intf;
{ TInftGenerator }
function TInftGenerator.GenerateIntfName(AIntf : TPasElement) : string;
begin
Result := AIntf.Name;
end;
function TInftGenerator.GenerateTypeText(AType : TPasType) : string;
var
t : TPasType;
begin
t := GetUltimeType(AType);
if not t.InheritsFrom(TPasArrayType) then begin
Result := t.Name;
end else begin
t := GetUltimeType(TPasArrayType(t).ElType);
Result := Format('java.util.List<%s>',[t.Name]);
end;
end;
procedure TInftGenerator.GenerateIntfProcParamsTypes(AProc : TPasProcedure);
var
locName : string;
procedure WriteRequestConstructor();
var
prmCnt,k : Integer;
prm : TPasArgument;
prms : TList2;
begin
Indent();
Write('public %s(',[locName]);
prms := AProc.ProcType.Args;
prmCnt := prms.Count;
if ( prmCnt > 0 ) then begin
IncIndent();
for k := 0 to Pred(prmCnt) do begin
prm := TPasArgument(prms[k]);
if (k > 0 ) then
Write(', ');
NewLine();
Indent();
Write('%s %s',[GenerateTypeText(prm.ArgType),prm.Name]);
end;
DecIndent();
NewLine();
Indent();
end;
WriteLn('){');
IncIndent();
if (prmCnt = 0) then begin
Indent();
WriteLn('super("%s", null);',[AProc.Name]);
end else begin
Indent();
Write('super("%s", new Object[] {',[AProc.Name]);
for k := 0 to Pred(prmCnt) do begin
prm := TPasArgument(prms[k]);
if (k > 0 ) then
Write(', ');
Write(prm.Name);
end;
WriteLn('});');
end;
DecIndent();
Indent();
WriteLn('}');
end;
procedure WriteResponseFields();
var
pt : TPasType;
begin
if AProc.InheritsFrom(TPasFunction) then begin
Indent();
pt := GetUltimeType(TPasFunctionType(AProc.ProcType).ResultEl.ResultType);
Write('public %s result',[GenerateTypeText(pt)]);
if pt.InheritsFrom(TPasArrayType) then
Write(' = new java.util.ArrayList<>()');
WriteLn(';');
end;
end;
var
locUnitName, s : string;
begin
locUnitName := GetDestUnitName();
locName := Format('%sInParamsEnv_Type',[AProc.Name]);
s := locUnitName + PathDelim + locName+ '.java';
FStream := SrcMngr.CreateItem(s);
SetCurrentStream(FStream);
WriteLn('package %s;',[locUnitName]);
NewLine();
WriteLn('public class %s extends wst.BaseRemoteRequest {',[locName]);
IncIndent();
WriteRequestConstructor();
DecIndent();
WriteLn('}');
locName := Format('%sOutParamsEnv_Type',[AProc.Name]);
s := locUnitName + PathDelim + locName+ '.java';
FStream := SrcMngr.CreateItem(s);
SetCurrentStream(FStream);
WriteLn('package %s;',[locUnitName]);
NewLine();
WriteLn('public class %s extends wst.BaseRemoteResponse {',[locName]);
IncIndent();
WriteResponseFields();
DecIndent();
WriteLn('}');
end;
procedure TInftGenerator.GenerateIntf(AIntf : TPasClassType);
var
locName : string;
procedure WriteMethod(AMthd : TPasProcedure);
var
prmCnt,k : Integer;
prm : TPasArgument;
prms : TList2;
pt : TPasType;
begin
Indent();
Write('public ');
prms := AMthd.ProcType.Args;
prmCnt := prms.Count;
if AMthd.InheritsFrom(TPasFunction) then begin
pt := TPasFunctionType(AMthd.ProcType).ResultEl.ResultType;
Write(GenerateTypeText(pt) + ' ');
end else begin
Write('void ');
end;
Write('%s(',[AMthd.Name]);
if ( prmCnt > 0 ) then begin
IncIndent();
for k := 0 to Pred(prmCnt) do begin
prm := TPasArgument(prms[k]);
if (k > 0 ) then
Write(', ');
NewLine();
Indent();
Write('%s %s',[GenerateTypeText(prm.ArgType),prm.Name]);
end;
DecIndent();
NewLine();
Indent();
end;
WriteLn(') throws java.io.IOException, wst.RemoteException;');
end;
procedure WriteMethods();
var
k, kc : Integer;
mbrs : TList2;
elt : TPasElement;
begin
IncIndent();
mbrs := AIntf.Members;
kc := 0;
for k := 0 to Pred(mbrs.Count) do begin
elt := TPasElement(mbrs[k]);
if elt.InheritsFrom(TPasProcedure) then begin
if (kc > 0) then
NewLine();
kc := kc+1;
WriteMethod(TPasProcedure(elt));
end;
end;
DecIndent();
end;
procedure WriteMethodEnvs();
var
k : Integer;
mbrs : TList2;
elt : TPasElement;
begin
mbrs := AIntf.Members;
for k := 0 to Pred(mbrs.Count) do begin
elt := TPasElement(mbrs[k]);
if elt.InheritsFrom(TPasProcedure) then
GenerateIntfProcParamsTypes(TPasProcedure(elt));
end;
end;
var
locUnitName, s : string;
begin
locUnitName := GetDestUnitName();
s := locUnitName + PathDelim + SymbolTable.GetExternalName(AIntf)+ '.java';
FStream := SrcMngr.CreateItem(s);
SetCurrentStream(FStream);
WriteLn('package %s;',[locUnitName]);
NewLine();
locName := GenerateIntfName(AIntf);
WriteLn('public interface %s {',[locName]);
IncIndent();
WriteMethods();
DecIndent();
WriteLn('}');
WriteMethodEnvs();
end;
procedure TInftGenerator.GenerateIntfProxy(AIntf : TPasClassType);
var
locProxyName : string;
procedure WriteMethod(AMthd : TPasProcedure);
var
prmCnt,k : Integer;
prm : TPasArgument;
prms : TList2;
s : string;
pt : TPasType;
begin
Indent();
Write('public ');
prms := AMthd.ProcType.Args;
prmCnt := prms.Count;
if AMthd.InheritsFrom(TPasFunction) then begin
pt := TPasFunctionType(AMthd.ProcType).ResultEl.ResultType;
Write(GenerateTypeText(pt) + ' ');
end else begin
Write('void ');
end;
Write('%s(',[AMthd.Name]);
if ( prmCnt > 0 ) then begin
IncIndent();
for k := 0 to Pred(prmCnt) do begin
prm := TPasArgument(prms[k]);
if (k > 0 ) then
Write(', ');
NewLine();
Indent();
Write('%s %s',[GenerateTypeText(prm.ArgType),prm.Name]);
end;
DecIndent();
NewLine();
Indent();
end;
WriteLn(') throws java.io.IOException, wst.RemoteException{');
IncIndent();
s := Format('%sInParamsEnv_Type',[AMthd.Name]);
Indent();
Write('%s request = new %s(',[s,s]);
for k := 0 to Pred(prmCnt) do begin
prm := TPasArgument(prms[k]);
if (k > 0 ) then
Write(', ');
Write(prm.Name);
end;
WriteLn(');');
s := Format('%sOutParamsEnv_Type',[AMthd.Name]);
Indent();
WriteLn('%s response = (%s)MakeCall(request, %s.class);',[s,s,s]);
Indent();
WriteLn('if (response.error != null){ ');
IncIndent();
Indent();
WriteLn('throw new wst.RemoteException(response.error.message,response.error.code,response.error.name);');
DecIndent();
Indent();
WriteLn('}');
if AMthd.InheritsFrom(TPasFunction) then begin
Indent();
WriteLn('return response.result;');
end;
DecIndent();
Indent();
WriteLn('};');
end;
procedure WriteMethods();
var
k : Integer;
mbrs : TList2;
elt : TPasElement;
begin
IncIndent();
mbrs := AIntf.Members;
for k := 0 to Pred(mbrs.Count) do begin
elt := TPasElement(mbrs[k]);
if elt.InheritsFrom(TPasProcedure) then begin
NewLine();
WriteMethod(TPasProcedure(elt));
end;
end;
DecIndent();
end;
var
locUnitName, s : string;
begin
locUnitName := GetDestUnitName();
locProxyName := ExtractserviceName(AIntf);
locProxyName := Format('%sProxy',[locProxyName]);
s := locUnitName + PathDelim + locProxyName + '.java';
FStream := SrcMngr.CreateItem(s);
SetCurrentStream(FStream);
WriteLn('package %s;',[locUnitName]);
NewLine();
WriteLn('public class %s extends wst.BaseProxy implements %s {',[locProxyName,AIntf.Name]);
IncIndent();
Indent();
WriteLn('public %s(String serviceAddress){',[locProxyName]);
IncIndent();
Indent();
WriteLn('super(serviceAddress);');
DecIndent();
Indent();
WriteLn('}');
DecIndent();
WriteMethods();
WriteLn('}');
end;
procedure TInftGenerator.GenerateClass(ASymbol : TPasClassType);
procedure WriteDec();
var
decBuffer, s : string;
elt : TPasElement;
ultimAnc, trueAncestor : TPasType;
begin
s := '';
if Assigned(ASymbol.AncestorType) then begin
trueAncestor := ASymbol.AncestorType;
if trueAncestor.InheritsFrom(TPasUnresolvedTypeRef) then begin
elt := SymbolTable.FindElement(SymbolTable.GetExternalName(trueAncestor));
if (elt = nil) or (not elt.InheritsFrom(TPasType)) then
trueAncestor := nil
else
trueAncestor := TPasType(elt);
end;
if (trueAncestor <> nil) then begin
trueAncestor := GetUltimeType(trueAncestor);
if trueAncestor.InheritsFrom(TPasNativeSimpleType) and
Assigned(TPasNativeSimpleType(trueAncestor).ExtendableType)
then begin
trueAncestor := TPasNativeSimpleType(trueAncestor).ExtendableType;
end;
if not(trueAncestor.InheritsFrom(TPasNativeClassType)) or (trueAncestor.Name <> 'Object') then
s := Format('%s',[trueAncestor.Name]);
end;
end;
if IsStrEmpty(s) then
decBuffer := ''
else
decBuffer := Format(' extends %s',[s]);
Indent();
WriteLn('public class %s%s {',[ASymbol.Name,decBuffer]);
end;
procedure WriteProperty(AProp : TPasProperty; AActualPropType : TPasType);
var
locLine : string;
locType : TPasType;
locIsArray : Boolean;
begin
locType := GetUltimeType(AActualPropType);
locIsArray := SymbolTable.IsOfType(locType,TPasArrayType);
if not locIsArray then begin
locLine := Format('public %s %s',[GenerateTypeText(locType),SymbolTable.GetExternalName(AProp)]);
if SymbolTable.IsOfType(locType,TPasClassType) then
locLine := Format('%s = new %s()',[locLine,GenerateTypeText(locType)]);
locLine := locLine+';';
end else begin
locType := GetUltimeType(TPasArrayType(locType).ElType);
locLine := Format('public java.util.List<%s> %s = new java.util.ArrayList<>();',[GenerateTypeText(locType),SymbolTable.GetExternalName(AProp)]);
end;
Indent(); WriteLn(locLine);
end;
procedure WriteProperties();
var
k : Integer;
p : TPasProperty;
elt : TPasElement;
begin
Indent();
IncIndent();
for k := 0 to Pred(ASymbol.Members.Count) do begin
elt := TPasElement(ASymbol.Members[k]);
if elt.InheritsFrom(TPasProperty) then begin
p := TPasProperty(elt);
WriteProperty(p,FindActualType(p.VarType,SymbolTable));
end;
end;
DecIndent();
end;
begin
try
NewLine();
WriteDec();
WriteProperties();
WriteLn('}');
except
on e : Exception do begin
GetLogger.Log(mtError,'TInftGenerator.GenerateClass()=',[ASymbol.Name, ' ;; ', e.Message]);
raise;
end;
end;
end;
procedure TInftGenerator.GenerateEnum(ASymbol : TPasEnumType);
var
i : Integer;
itm : TPasEnumValue;
s : string;
begin
NewLine();
WriteLn('public enum %s {',[SymbolTable.GetExternalName(ASymbol)]);
IncIndent();
for i := 0 to Pred(ASymbol.Values.Count) do begin
itm := TPasEnumValue(ASymbol.Values[i]);
Indent();
s := SymbolTable.GetExternalName(itm);
if ( i > 0 ) then
WriteLn(',%s',[s])
else
WriteLn('%s',[s]);
end;
DecIndent();
WriteLn('}');
end;
function TInftGenerator.GetDestUnitName(): string;
begin
Result := SymbolTable.CurrentModule.Name;
end;
procedure TInftGenerator.GenerateEnums();
var
typeList : TList2;
locUnitName, s : string;
i, c : Integer;
elt : TPasElement;
begin
typeList := SymbolTable.CurrentModule.InterfaceSection.Declarations;
c := typeList.Count;
for i := 0 to c-1 do begin
elt := TPasElement(typeList[i]);
if elt.InheritsFrom(TPasEnumType) then begin
locUnitName := GetDestUnitName();
s := locUnitName + PathDelim + SymbolTable.GetExternalName(elt)+ '.java';
FStream := SrcMngr.CreateItem(s);
SetCurrentStream(FStream);
WriteLn('package %s;',[locUnitName]);
GenerateEnum(TPasEnumType(elt));
end;
end;
end;
procedure TInftGenerator.PrepareModule();
begin
end;
procedure TInftGenerator.InternalExecute();
var
i, c, j, k : Integer;
clssTyp : TPasClassType;
gnrClssLst : TObjectList;
objLst : TObjectList;
typeList : TList2;
elt : TPasElement;
classAncestor : TPasElement;
s, locUnitName : string;
begin
GenerateEnums();
objLst := nil;
gnrClssLst := TObjectList.Create(False);
try
locUnitName := GetDestUnitName();
typeList := SymbolTable.CurrentModule.InterfaceSection.Declarations;
c := Pred(typeList.Count);
objLst := TObjectList.Create();
objLst.OwnsObjects := False;
for i := 0 to c do begin
elt := TPasElement(typeList[i]);
if elt.InheritsFrom(TPasClassType) and ( TPasClassType(elt).ObjKind = okClass ) then begin
clssTyp := TPasClassType(elt);
if ( gnrClssLst.IndexOf(clssTyp) = -1 ) then begin
objLst.Clear();
while Assigned(clssTyp) and ( objLst.IndexOf(clssTyp) = -1 ) do begin
objLst.Add(clssTyp);
classAncestor := clssTyp.AncestorType;
if Assigned(classAncestor) and classAncestor.InheritsFrom(TPasUnresolvedTypeRef) then begin
classAncestor := SymbolTable.FindElement(SymbolTable.GetExternalName(classAncestor));
end;
if Assigned(classAncestor) and classAncestor.InheritsFrom(TPasClassType) then begin
clssTyp := classAncestor as TPasClassType;
end else begin
clssTyp := nil;
end;
end;
k := Pred(objLst.Count);
for j := 0 to k do begin
clssTyp := objLst[k-j] as TPasClassType;
if ( gnrClssLst.IndexOf(clssTyp) = -1 ) then begin
if ( SymbolTable.CurrentModule.InterfaceSection.Declarations.IndexOf(clssTyp) <> -1 ) then begin
s := locUnitName + PathDelim + SymbolTable.GetExternalName(clssTyp)+ '.java';
FStream := SrcMngr.CreateItem(s);
SetCurrentStream(FStream);
WriteLn('package %s;',[locUnitName]);
GenerateClass(clssTyp);
gnrClssLst.Add(clssTyp);
end;
end;
end;
end;
end;
end;
for i := 0 to c do begin
elt := TPasElement(typeList[i]);
if elt.InheritsFrom(TPasClassType) and ( TPasClassType(elt).ObjKind = okInterface ) then begin
GenerateIntf(TPasClassType(elt));
GenerateIntfProxy(TPasClassType(elt));
end;
end;
finally
FreeAndNil(objLst);
FreeAndNil(gnrClssLst);
end;
end;
procedure TInftGenerator.Execute();
var
oldCurrent, mdl : TPasModule;
i : Integer;
mdlList : TList2;
oldCS : Boolean;
oldNamesKinds : TElementNameKinds;
begin
oldCS := SymbolTable.CaseSensitive;
oldNamesKinds := SymbolTable.DefaultSearchNameKinds;
oldCurrent := SymbolTable.CurrentModule;
try
SymbolTable.CaseSensitive := True;
SymbolTable.DefaultSearchNameKinds := [elkDeclaredName];
mdlList := SymbolTable.Package.Modules;
for i := 0 to Pred(mdlList.Count) do begin
mdl := TPasModule(mdlList[i]);
if not mdl.InheritsFrom(TPasNativeModule) then begin
SymbolTable.SetCurrentModule(mdl);
PrepareModule();
InternalExecute();
end;
end;
finally
SymbolTable.SetCurrentModule(oldCurrent);
SymbolTable.CaseSensitive := oldCS;
SymbolTable.DefaultSearchNameKinds := oldNamesKinds;
end;
end;
end.