Componentes.Terceros.RemObj.../internal/5.0.24.615/1/RemObjects SDK for Delphi/Source/uRODL.pas

2073 lines
57 KiB
ObjectPascal

unit uRODL;
{----------------------------------------------------------------------------}
{ RemObjects SDK Library - Core Library }
{ }
{ compiler: Delphi 5 and up, Kylix 2 and up }
{ platform: Win32, Linux }
{ }
{ (c)opyright RemObjects Software. all rights reserved. }
{ }
{ Using this code requires a valid license of the RemObjects SDK }
{ which can be obtained at http://www.remobjects.com. }
{----------------------------------------------------------------------------}
{$I RemObjects.inc}
interface
uses
{$IFDEF REMOBJECTS_TRIAL}uROTrial, {$ENDIF}
Classes, Contnrs, uROClasses;
const
EmptyGUID: TGUID = (D1: 0; D2: 0; D3: 0; D4: (0, 0, 0, 0, 0, 0, 0, 0));
DefaultIntfName = 'Default';
type
{ Misc types }
TRODLParamFlag = (fIn, fOut, fInOut, fResult);
const
RODLParamFlagNames: array[TRODLParamFlag] of string = ('in', 'out', 'in/out', 'result');
type
{ TRODLNameInfo }
TRODLEntity = class;
TRODLLibrary = class;
TRoPluginMessageType = (rmtInfo, rmtHint, rmtWarning, rmtError, rmtSuccess, rmtCustom);
IROPluginMessages = interface
['{9B07B5C2-FC07-4B9B-9207-D487CDC58D0E}']
procedure AddMessage(iType:TRoPluginMessageType; const iSource, iMessage:string; aReserved:integer=-1; aEntity:TRODLEntity=nil);
end;
IRODLEntityWithAncestor = interface
['{88D59A20-5B47-4CF0-A06C-C135EB598B12}']
function GetAncestor:string;
procedure SetAncestor(const iValue:string);
property Ancestor:string read GetAncestor write SetAncestor;
end;
TRODLUse = class;
TRODLGroup = class;
{ TRODLEntity }
TRODLEntity = class(TObject, IUnknown)
private
fIsFromUsedRodl: boolean;
fLocatedInRodlUse: TRODLUse;
fOwner:TRODLEntity;
fData: TObject;
fGroupUnder: TRODLGroup;
fName: string;
fAttributes: TStringList;
fDocumentation: string;
fUID: TGUID;
procedure SetName(const Value: string); virtual;
procedure SetDocumentation(const Value: string);
function GetAttributes: TStrings;
function GetInfo: TRODLEntity;
function GetOwnerLibrary: TRODLLibrary;
protected
function _AddRef: Integer; stdcall;
function _Release: Integer; stdcall;
function QueryInterface(const IID: TGUID; out Obj): HRESULT; stdcall;
public
constructor Create; virtual;
destructor Destroy; override;
procedure Validate(iMessages:IRoPluginMessages); virtual;
//function Validate(out FaultyEntity: TRODLEntity; out ErrorMessage: string): boolean; virtual;
property Name: string read fName write SetName;
property Documentation: string read fDocumentation write SetDocumentation;
property UID: TGUID read fUID write fUID;
property Attributes: TStrings read GetAttributes;
property Owner:TRODLEntity read fOwner;
property OwnerLibrary:TRODLLibrary read GetOwnerLibrary;
property Info: TRODLEntity read GetInfo; { for backwards comatibility }
property IsFromUsedRodl:boolean read fIsFromUsedRodl write fIsFromUsedRodl;
property LocatedInRodlUse:TRODLUse read fLocatedInRodlUse write fLocatedInRodlUse;
{ Helpers for visual representation in SB and elsewhere }
property GroupUnder:TRODLGroup read fGroupUnder write fGroupUnder;
class function ReadableEntityTypeName: string;
{ Properties to hold custom application-specific data at runtime, for
the application coding convenience. These are not persisted in any way }
property Data:TObject read fData write fData;
end;
TRODLEntityClass = class of TRODLEntity;
TRODLGroup = class(TRODLEntity)
end;
{ TRODLComplexEntity }
TRODLComplexEntity = class(TRODLEntity)
private
fItems: TObjectList;
fAutoCreateParams: boolean;
fAbstract: boolean;
function GetCount: integer;
function GetItems(Index: integer): TRODLEntity;
protected
function GetItemClass: TRODLEntityClass; virtual; abstract;
public
constructor Create; override;
destructor Destroy; override;
procedure Validate(iMessages:IRoPluginMessages); override;
//function Validate(out FaultyEntity: TRODLEntity; out ErrorMessage: string): boolean; override;
function ContainsEntity(aEntity: TRODLEntity; aRecurse:boolean=true):boolean;
function ItemByName(const aName: string): TRODLEntity;
function ItemByUID(const aUID: TGUID): TRODLEntity;
function Add(anEntity: TRODLEntity): integer; overload; virtual;
function Add: TRODLEntity; overload; virtual;
procedure Insert(aIndex: integer; anEntity: TRODLEntity); overload; virtual;
function Insert(aIndex: integer): TRODLEntity; overload; virtual;
function UniqueName(aBaseName:string):string;
procedure Exchange(Index1, Index2: integer); virtual;
procedure Remove(anEntity: TRODLEntity); virtual;
procedure Delete(Index: integer); virtual;
procedure Clear;
procedure Sort;
property AutoCreateParams:boolean read fAutoCreateParams write fAutoCreateParams;
property Abstract:boolean read fAbstract write fAbstract;
property ItemClass: TRODLEntityClass read GetItemClass;
property Items[Index: integer]: TRODLEntity read GetItems; default;
property Count: integer read GetCount;
end;
{ TRODLTypedEntity }
TRODLTypedEntity = class(TRODLEntity)
private
fDataType: string;
procedure SetDataType(const Value: string);
public
procedure Validate(iMessages: IRoPluginMessages); override;
property DataType: string read fDataType write SetDataType;
end;
{ TRODLStruct }
TRODLBaseStruct = class(TRODLComplexEntity, IRODLEntityWithAncestor)
private
fAncestor: string;
function GetItems(Index: integer): TRODLTypedEntity;
procedure SetAncestor(const Value: string);
protected
function GetItemClass: TRODLEntityClass; override;
public
function Add(aStructElement: TRODLTypedEntity): integer; reintroduce; overload;
function Add: TRODLTypedEntity; reintroduce; overload;
procedure Validate(iMessages:IRoPluginMessages); override;
property Items[Index: integer]: TRODLTypedEntity read GetItems; default;
property Ancestor: string read fAncestor write SetAncestor;
function GetAncestor: string;
function CalcItemsMarshalingOrder(aIncludeAncestors: boolean=true): IROStrings;
end;
TRODLStruct = class(TRODLBaseStruct);
{ TRODLArray }
TRODLArray = class(TRODLEntity)
private
fElementType: string;
procedure SetElementType(const Value: string);
public
procedure Validate(iMessages:IRoPluginMessages); override;
//function Validate(out FaultyEntity: TRODLEntity; out ErrorMessage: string): boolean; override;
property ElementType: string read fElementType write SetElementType;
end;
{ TRODLEnumValue }
TRODLEnumValue = class(TRODLEntity)
private
end;
{ TRODLEnum }
TRODLEnum = class(TRODLComplexEntity)
private
fPrefixEnumValues: Boolean;
function GetItems(Index: integer): TRODLEnumValue;
protected
function GetItemClass: TRODLEntityClass; override;
public
constructor Create; override;
function Add(aStructElement: TRODLEnumValue): integer; reintroduce; overload;
function Add: TRODLEnumValue; reintroduce; overload;
procedure Validate(iMessages:IRoPluginMessages); override;
property Items[Index: integer]: TRODLEnumValue read GetItems; default;
property PrefixEnumValues: Boolean read fPrefixEnumValues write fPrefixEnumValues;
end;
{ TRODLOperationParam }
TRODLOperationParam = class(TRODLTypedEntity)
private
fFlag: TRODLParamFlag;
function GetFlag: string;
procedure SetFlag(const aValue: string);
public
property Flag: TRODLParamFlag read fFlag write fFlag;
property FlagAsString: string read GetFlag write SetFlag;
end;
{ TRODLOperation }
TRODLOperation = class(TRODLComplexEntity)
private
fOperationResult: TRODLOperationParam;
fCodeBodies: TStringList;
fForceAsyncResponse: boolean;
function GetItems(Index: integer): TRODLOperationParam;
function GetResult: TRODLOperationParam;
function GetCodeBody(iLanguage: string): TStrings;
function GetCodeBodyCount: integer;
function GetCodeBodyLanguages(iIndex: integer): string;
protected
function GetItemClass: TRODLEntityClass; override;
public
constructor Create; override;
destructor Destroy; override;
function Add(aParam: TRODLOperationParam): integer; reintroduce; overload;
function Add: TRODLOperationParam; reintroduce; overload;
{procedure MoveResult();
procedure Exchange(Index1, Index2: integer); override;}
procedure SetCodeBody(iLanguage: string; Value: TStrings);
procedure SetCodeBodyAsString(iLanguage: string; const Value: string);
function GetParameter(const aParameterName : string) : TRODLOperationParam;
property Items[Index: integer]: TRODLOperationParam read GetItems; default;
property Result: TRODLOperationParam read GetResult;
function AddResult: TRODLOperationParam;
procedure RemoveResult;
property ForceAsyncResponse:boolean read fForceAsyncResponse write fForceAsyncResponse;
property CodeBodies[iLanguage:string]:TStrings read GetCodeBody write SetCodeBody;
property CodeBodyCount:integer read GetCodeBodyCount;
property CodeBodyLanguages[iIndex:integer]:string read GetCodeBodyLanguages;
procedure Validate(iMessages: IROPluginMessages); override;
end;
{ TRODLServiceInterface }
TRODLServiceInterface = class(TRODLComplexEntity)
private
function GetItems(Index: integer): TRODLOperation;
protected
function GetItemClass: TRODLEntityClass; override;
public
procedure GetOperationsList(AList: TList);
function FindOperation(const anOperationName : string; IncludeAnchestors : boolean = FALSE) : TRODLOperation;
function GetOperation(const anOperationName : string; IncludeAnchestors : boolean = FALSE) : TRODLOperation;
function Add(aParam: TRODLOperation): integer; reintroduce; overload;
function Add: TRODLOperation; reintroduce; overload;
property Items[Index: integer]: TRODLOperation read GetItems; default;
end;
{ TRODLBaseService }
TRODLBaseService = class(TRODLComplexEntity, IRODLEntityWithAncestor)
private
fAncestor: string;
fImplClass: string;
fImplUnit: string;
fisPrivate: Boolean;
function GetItems(Index: integer): TRODLServiceInterface;
function GetDefault: TRODLServiceInterface;
procedure SetAncestor(const Value: string);
protected
function GetItemClass: TRODLEntityClass; override;
public
constructor Create; override;
function Add(aServiceInterface: TRODLServiceInterface): integer; reintroduce; overload;
function Add: TRODLServiceInterface; reintroduce; overload;
procedure Validate(iMessages: IRoPluginMessages); override;
property Items[Index: integer]: TRODLServiceInterface read GetItems; default;
property Default: TRODLServiceInterface read GetDefault;
property Ancestor: string read fAncestor write SetAncestor;
property ImplUnit:string read fImplUnit write fImplUnit;
property ImplClass:string read fImplClass write fImplClass;
function GetAncestor:string;
property isPrivate: Boolean read fisPrivate write fisPrivate;
end;
TRODLService = class(TRODLBaseService);
TRODLEventSink = class(TRODLBaseService);
{ TRODLArray }
TRODLException = class(TRODLBaseStruct)
public
procedure Validate(iMessages:IRoPluginMessages); override;
end;
{ TRODLUse }
TRODLUse = class(TRODLEntity)
private
fRodlFile: string;
fAbsoluteRodlFile: string;
fLoadedRodlLibraryName: string;
fGenerateCode: boolean;
public
procedure Validate(iMessages:IRoPluginMessages); override;
property RodlFile:string read fRodlFile write fRodlFile;
property AbsoluteRodlFile:string read fAbsoluteRodlFile write fAbsoluteRodlFile;
property LoadedRodlLibraryName: string read fLoadedRodlLibraryName write fLoadedRodlLibraryName;
property GenerateCode: boolean read fGenerateCode write fGenerateCode;
end;
{ TRODLLibrary }
TRODLLibrary = class(TRODLComplexEntity)
private
fArrayCount: integer;
fServiceCount: integer;
fStructCount: integer;
fEnumCount: integer;
fExceptionCount: integer;
fUseCount: integer;
fEventSinkCount: integer;
fGroupCount: integer;
fRodlFilename: string;
fNamespace: string;
function GetByType(aIndex:integer; aType:TRODLEntityClass):TRODLEntity;
function GetArray(Index: integer): TRODLArray;
function GetEnums(Index: integer): TRODLEnum;
function GetServices(Index: integer): TRODLService;
function GetStructs(Index: integer): TRODLStruct;
function GetExceptions(Index: integer): TRODLException;
function GetUse(Index: integer): TRODLUse;
function CalcOrder(const iObjects: IROStrings): IROStrings;
function GetGroups(Index: integer): TRODLGroup;
function GetEventSinks(Index: integer): TRODLEventSink;
protected
function GetItemClass: TRODLEntityClass; override;
public
constructor Create(); override;
procedure GetArraysByElement(const aElementName:string; AList: TList);
function FindService(const iServiceName: string): TRODLService;
function FindStruct(const iStructName: string): TRODLStruct;
function FindBaseStruct(const iStructName: string): TRODLBaseStruct;
function FindEnum(const iEnumName: string): TRODLEnum;
function FindArray(const iArrayName: string): TRODLArray;
function FindGroup(const aID: TGUID): TRODLGroup; overload;
function FindException(const iExceptionName: string): TRODLException;
function FindUse(const iUseName: string): TRODLUse;
function FindUseByFilename(const iUseRODLFile: string): TRODLUse;
procedure ClearDuplicates();
function GetService(const aServiceName: string): TRODLService;
function GetStruct(const aStructName: string): TRODLStruct;
function IsValidCustomType(const iTypeName:string):boolean;
function IsValidSimpleType(const iTypeName: string): boolean;
function IsValidType(const iTypeName:string):boolean;
function IsValidService(const iServiceName:string):boolean;
function IsValidEventSink(const iEventSink:string):boolean;
function IsValidException(const iTypeName:string):boolean;
function Add(anEntity: TRODLEntity): integer; override;
function CalcServiceOrder:IROStrings;
function CalcEventSinkOrder: IROStrings;
function CalcExceptionOrder: IROStrings;
function CalcStructOrder: IROStrings;
procedure Delete(Index: integer); override;
procedure Remove(anEntity: TRODLEntity); override;
property RodlFilename:string read fRodlFilename write fRodlFilename;
property Namespace: string read fNamespace write fNamespace;
property Structs[Index: integer]: TRODLStruct read GetStructs;
property StructCount: integer read fStructCount;
property Arrays[Index: integer]: TRODLArray read GetArray;
property ArrayCount: integer read fArrayCount;
property Enums[Index: integer]: TRODLEnum read GetEnums;
property EnumCount: integer read fEnumCount;
property Services[Index: integer]: TRODLService read GetServices;
property ServiceCount: integer read fServiceCount;
property Exceptions[Index: integer]: TRODLException read GetExceptions;
property ExceptionCount: integer read fExceptionCount;
property Use[Index: integer]: TRODLUse read GetUse;
property UseCount: integer read fUseCount;
property Groups[Index: integer]: TRODLGroup read GetGroups;
property GroupCount: integer read fGroupCount;
property EventSinks[Index: integer]: TRODLEventSink read GetEventSinks;
property EventSinkCount: integer read fEventSinkCount;
end;
{ TRODLConverter }
TRODLConverter = class
private
fBuffer: TStringList;
fTargetEntity: string;
function GetBuffer: TStrings;
protected
procedure IntConvert(const aLibrary: TRODLLibrary; const aTargetEntity: string = ''); virtual; abstract;
function ValidateTargetEntity(const aLibrary: TRODLLibrary; const aTargetEntity: string): boolean; virtual;
public
constructor Create(const aLibraryFile: string; const aTargetEntity: string = ''); overload; virtual;
constructor Create(const aLibrary: TRODLLibrary; const aTargetEntity: string = ''); overload; virtual;
destructor Destroy; override;
procedure Write(const someText: string; Indentation: integer = 0); overload;
procedure WriteLines(const someText: string);
procedure WriteEmptyLine;
procedure Convert(const aLibrary: TRODLLibrary; const aTargetEntity: string = '');
class function GetTargetFileName(const aLibrary: TRODLLibrary; const aTargetEntity: string = ''): string; virtual;
property Buffer: TStrings read GetBuffer;
property TargetEntity: string read fTargetEntity;
end;
TRODLConverterClass = class of TRODLConverter;
{ TRODLReader }
TRODLReader = class
private
protected
function IntReadFromStream(aStream: TStream; aFilename:string): TRODLLibrary; virtual; abstract;
public
constructor Create; virtual;
function Read(aStream: TStream; const aFilename:string=''): TRODLLibrary;
function ReadFromFile(const aFileName: string): TRODLLibrary;
end;
TRODLReaderClass = class of TRODLReader;
function ReadRODLFromFile(aReaderClass: TRODLReaderClass; const aFileName: string): TRODLLibrary;
function ExpandVariables(const aFilename:string):string;
implementation
uses
{$IFDEF DEBUG_REMOBJECTS_RODL}eDebugServer, {$ENDIF}
{$IFDEF DELPHI5} ActiveX, Windows, {$ENDIF}
{$IFDEF MSWINDOWS}Registry, {$IFNDEF DELPHI5}Windows,{$ENDIF}{$ENDIF}
SysUtils, TypInfo, uRORes, uRODLToXML, uROTypes, Math;
{ Support routines }
{$IFDEF MSWINDOWS}
function LookupVariable(const aVariable:string):string;
begin
with TRegistry.Create do try
RootKey := HKEY_CURRENT_USER;
OpenKey('Software\RemObjects\RemObjects SDK\Variables',false);
result := ReadString(aVariable);
{ if result = '' then
RaiseError('Variable $(%s) used in RODL is not defined.',[aVariable]);
}
finally
Free;
end;
end;
{$ENDIF}
{$IFDEF MSWINDOWS}
function ExpandVariables(const aFilename:string):string;
var
p: Integer;
lName,lVar:string;
begin
lName := aFilename;
if Pos('$(',lName) = 1 then begin
p := Pos(')',lName);
if p > 1 then begin
lVar := Copy(lName,3,p-3);
Delete(lName,1,p);
result := LookupVariable(lVar)+lName;
exit;
end;
end;
result := aFilename;
end;
{$ELSE}
function ExpandVariables(const aFilename:string):string;
begin
result := aFilename;
end;
{$ENDIF}
function CleanupText(const someText: string): string;
var
i: integer;
begin
result := Trim(someText);
for i := 1 to Length(result) do
case result[i] of
'0'..'9': begin
if (i = 1) then result[i] := '_';
end;
'a'..'z',
'A'..'Z',
'_': Continue;
else
result[i] := '_';
end;
end;
function CleanupTextAllowSpaces(const someText: string): string;
var
i: integer;
begin
result := Trim(someText);
for i := 1 to Length(result) do
case result[i] of
{'0'..'9' : begin
if (i=1) then result[i] := '_';
end;}
#13, #10, #09,
#$20..#$21,
#$23..#$25,
#$27..#$3b,
#$3d,
#$3f..#$7e: Continue;
else
result[i] := '_';
end;
end;
function ReadRODLFromFile(aReaderClass: TRODLReaderClass; const aFileName: string): TRODLLibrary;
begin
with aReaderClass.Create do try
result := ReadFromFile(aFileName);
finally
Free;
end;
end;
{ TRODLNameInfo }
{constructor TRODLNameInfo.Create(const aName: string; aOwner:TRODLEntity);
begin
Name := aName;
fOwner := aOwner;
fUID := NewUID();
end;
destructor TRODLNameInfo.Destroy;
begin
if Assigned(fAttributes) then fAttributes.Free;
inherited;
end;
function TRODLNameInfo.GetAttributes: TStrings;
begin
if (fAttributes = nil) then fAttributes := TStringList.Create;
result := fAttributes;
end;
procedure TRODLNameInfo.SetName(const Value: string);
begin
fName := CleanupText(Value);
end;
procedure TRODLNameInfo.SetDocumentation(const Value: string);
begin
fDocumentation := CleanupTextAllowSpaces(Value);
end; }
{ TRODLEntityInfo }
{constructor TRODLEntityInfo.Create(const aName: string; const aUID: TGUID; const someDocumentation: string; aOwner:TRODLEntity);
begin
inherited Create(aName,aOwner);
UID := aUID;
Documentation := someDocumentation;
end;}
{procedure TRODLEntityInfo.Validate(iMessages:IRoPluginMessages);
//function TRODLEntityInfo.GetIsValid: boolean;
begin
//result := inherited GetIsValid and
if IsEqualGUID(UID, EmptyGUID) then
iMessages.AddMessage(rmtWarning,Name,'No UID specified',-1,Owner);
end;}
{ TRODLEntity }
constructor TRODLEntity.Create;
begin
fUID := NewGUID();
end;
destructor TRODLEntity.Destroy;
begin
if Assigned(fAttributes) then fAttributes.Free;
inherited;
end;
function TRODLEntity.GetInfo: TRODLEntity;
begin
result := self;
end;
procedure TRODLEntity.Validate(iMessages:IRoPluginMessages);
begin
if (Trim(Name) = '') then
iMessages.AddMessage(rmtError,'','No Name specified',-1,Owner);
{ ToDo: add a flag that specified whether UID is needed for the explicit base types }
if IsEqualGUID(UID, EmptyGUID) then
iMessages.AddMessage(rmtWarning,Name,'No UID specified',-1,Owner);
{result := Info.IsValid;
if not result then begin
FaultyEntity := Self;
ErrorMessage := err_InvalidInfo;
end;}
end;
function TRODLEntity.GetOwnerLibrary: TRODLLibrary;
var lOwner:TRODLEntity;
begin
lOwner := fOwner;
while Assigned(lOwner) and (not (lOwner is TRODLLibrary)) do
lOwner := lOwner.Owner;
Assert(Assigned(lOwner));
result := lOwner as TRODLLibrary;
end;
function TRODLEntity._AddRef: Integer;
begin
result := 1;
end;
function TRODLEntity._Release: Integer;
begin
result := 1;
end;
function TRODLEntity.QueryInterface(const IID: TGUID; out Obj): HRESULT;
begin
if GetInterface(IID, Obj) then
Result := 0
else
Result := E_NOINTERFACE;
end;
class function TRODLEntity.ReadableEntityTypeName: string;
begin
result := ClassName;
Delete(result,1,5); { delete the "TRODL" }
end;
function TRODLEntity.GetAttributes: TStrings;
begin
if (fAttributes = nil) then fAttributes := TStringList.Create;
result := fAttributes;
end;
procedure TRODLEntity.SetDocumentation(const Value: string);
begin
fDocumentation := Value;
end;
procedure TRODLEntity.SetName(const Value: string);
begin
fName := CleanupText(Value);
end;
{ TRODLComplexEntity }
function TRODLComplexEntity.Add(anEntity: TRODLEntity): integer;
begin
if not (anEntity is ItemClass) then RaiseError(err_InvalidType, [anEntity.ClassName, ItemClass.ClassName]);
result := fItems.Add(anEntity);
anEntity.fOwner := self;
end;
function TRODLComplexEntity.Add: TRODLEntity;
begin
result := ItemClass.Create;
result.fOwner := self;
Add(result);
end;
procedure TRODLComplexEntity.Insert(aIndex: integer; anEntity: TRODLEntity);
begin
if not (anEntity is ItemClass) then RaiseError(err_InvalidType, [anEntity.ClassName, ItemClass.ClassName]);
fItems.Insert(aIndex, anEntity);
anEntity.fOwner := self;
end;
function TRODLComplexEntity.Insert(aIndex: integer): TRODLEntity;
begin
result := ItemClass.Create;
result.fOwner := self;
Insert(aIndex, result);
end;
procedure TRODLComplexEntity.Clear;
begin
fItems.Clear;
end;
constructor TRODLComplexEntity.Create;
begin
inherited;
fAutoCreateParams := true;
fItems := TObjectList.Create;
end;
procedure TRODLComplexEntity.Delete(Index: integer);
begin
fItems.Delete(Index);
end;
destructor TRODLComplexEntity.Destroy;
begin
fItems.Free;
inherited;
end;
function TRODLComplexEntity.GetCount: integer;
begin
result := fItems.Count
end;
procedure TRODLComplexEntity.Validate(iMessages:IRoPluginMessages);
//function TRODLComplexEntity.Validate(out FaultyEntity: TRODLEntity; out ErrorMessage: string): boolean;
var
i, n: integer;
begin
inherited Validate(iMessages);
//if not result then Exit;
//result := FALSE;
// Check type names are unique
for i := 0 to (Count - 2) do
for n := i + 1 to (Count - 1) do
if (CompareText(Items[i].Info.Name, Items[n].Info.Name) = 0) then begin
iMessages.AddMessage(rmtError,Info.Name+'.'+Items[i].Info.Name,err_RodlDuplicateName,-1,Items[n]);
{FaultyEntity := ;
ErrorMessage := Format(err_DuplicateName, [Items[n].Info.Name]);
Exit;}
end;
// Check they are all valid on a basic level
for i := 0 to (Count - 1) do
Items[i].Validate(iMessages);
//if not Items[i].Validate(FaultyEntity, ErrorMessage) then Exit;
//result := TRUE;
end;
function TRODLComplexEntity.GetItems(Index: integer): TRODLEntity;
begin
result := TRODLEntity(fItems[Index]);
end;
function TRODLComplexEntity.ItemByName(const aName: string): TRODLEntity;
var
i: integer;
begin
result := nil;
for i := 0 to (Count - 1) do
if (CompareText(Items[i].Info.Name, aName) = 0) then begin
result := Items[i];
Exit;
end;
end;
function TRODLComplexEntity.ItemByUID(const aUID: TGUID): TRODLEntity;
var
i: integer;
begin
result := nil;
for i := 0 to (Count - 1) do
if IsEqualGUID(Items[i].Info.UID, aUID) then begin
result := Items[i];
Exit;
end;
end;
procedure TRODLComplexEntity.Remove(anEntity: TRODLEntity);
begin
fItems.Remove(anEntity)
end;
procedure TRODLComplexEntity.Exchange(Index1, Index2: integer);
begin
fItems.Exchange(Index1, Index2);
end;
function TRODLComplexEntity.UniqueName(aBaseName: string): string;
var
i: Integer;
lIndex: Integer;
lOk: boolean;
begin
lIndex := 0;
result := aBasename;
repeat
lOk := true;
for i := 0 to Count-1 do begin
if result = Items[i].Info.Name then begin
inc(lIndex);
result := aBaseName+IntToStr(lIndex);
lOk := false;
end;
end; { for }
until lOk;
end;
function TRODLComplexEntity.ContainsEntity(aEntity: TRODLEntity; aRecurse:boolean=true): boolean;
var
i: Integer;
begin
result := false;
for i := 0 to Count-1 do begin
if Items[i] = aEntity then begin
result := true;
exit;
end;
if aRecurse and (Items[i] is TRODLComplexEntity) then begin
result := TRODLComplexEntity(Items[i]).ContainsEntity(aEntity);
if result then exit;
end;
end; { for }
end;
function SortItem(Item1, Item2: Pointer): Integer;
begin
Result := CompareText(TRODLEntity(Item1).Name, TRODLEntity(Item2).name);
end;
procedure TRODLComplexEntity.Sort;
begin
fItems.Sort(@SortItem);
end;
{ TRODLTypedEntity }
procedure TRODLTypedEntity.Validate(iMessages:IRoPluginMessages);
begin
if (DataType = '') then begin
iMessages.AddMessage(rmtError,Owner.Owner.Info.Name+'.'+Name,err_RodlNoDataTypeSpecified,-1,Owner);
exit;
end;
if not Owner.OwnerLibrary.IsValidType(DataType) then
iMessages.AddMessage(rmtError,Owner.Owner.Info.Name+'.'+Name,Format(err_RodlInvalidDataType,[DataType]),-1,Owner);
if not (Owner is TRODLOperation) then
begin
if (CompareText(DataType,Owner.Info.Name) = 0) then
iMessages.AddMessage(rmtError,Owner.Info.Name,Format(err_RodlStructCannotBeNested,[DataType]),-1,Owner);
end;
end;
procedure TRODLTypedEntity.SetDataType(const Value: string);
begin
fDataType := CleanupText(Value);
end;
{ TRODLStruct }
function TRODLBaseStruct.Add(aStructElement: TRODLTypedEntity): integer;
begin
result := inherited Add(aStructElement)
end;
function TRODLBaseStruct.Add: TRODLTypedEntity;
begin
result := TRODLTypedEntity(inherited Add);
result.Info.Name := 'Field' + IntToStr(Count);
end;
function CompareRODLBaseStructItems(List: TStringList; Index1, Index2: Integer): Integer;
begin
Result := CompareText(List[Index1], List[Index2]);
end;
function TRODLBaseStruct.CalcItemsMarshalingOrder(aIncludeAncestors: boolean=true): IROStrings;
var
lAncestor: TRODLBaseStruct;
i:integer;
begin
result := NewROStrings();
result.Sorted := True;
result.Duplicates := dupIgnore;
lAncestor := self;
repeat
for i := lAncestor.Count-1 downto 0 do
result.AddObject(lAncestor.Items[i].Name, lAncestor.Items[i]);
if lAncestor.Ancestor <> '' then
lAncestor := OwnerLibrary.FindBaseStruct(lAncestor.Ancestor)
else
lAncestor := nil;
until (not Assigned(lAncestor)) or (not aIncludeAncestors);
// Do not use "Result.Sorted" because it uses AnsiCompareText for the comparisons
// whereas the SortPropList method originally used via GetGetPropList in TROSerializer.ReadObject
// does a case insensitive ASCII based sort. Hence the need to do our own
// sorting that calls CompareText.
result.Sorted := False;
result.CustomSort(CompareRODLBaseStructItems);
end;
function TRODLBaseStruct.GetAncestor: string;
begin
result := fAncestor;
end;
function TRODLBaseStruct.GetItemClass;
begin
result := TRODLTypedEntity;
end;
function TRODLBaseStruct.GetItems(Index: integer): TRODLTypedEntity;
begin
result := TRODLTypedEntity(inherited Items[Index]);
end;
procedure TRODLBaseStruct.SetAncestor(const Value: string);
begin
fAncestor := Trim(Value);
end;
procedure TRODLBaseStruct.Validate(iMessages: IRoPluginMessages);
begin
inherited;
{ Hack: for exemptions, dont warn about missing elements }
{ ToDo: create a command base class for struct and exception, and derrive both, to avoid this kind of prob. }
if (Count = 0) and not (self is TRODLException) and (Ancestor = '') then
iMessages.AddMessage(rmtWarning,Info.Name,err_RodlNoStructElementsDefined,-1,self);
if (Ancestor <> '') and not OwnerLibrary.IsValidType(Ancestor) and not (self is TRODLException) then // exceptions ancestors are checked in TRODLException.Validate
iMessages.AddMessage(rmtError,Info.Name,Format(err_RodlInvalidAncestorType,[Ancestor]),-1,self);
end;
{ TRODLEnum }
function TRODLEnum.Add(aStructElement: TRODLEnumValue): integer;
begin
result := inherited Add(aStructElement)
end;
function TRODLEnum.Add: TRODLEnumValue;
begin
result := TRODLEnumValue(inherited Add);
result.Info.Name := 'Value' + IntToSTr(Count);
end;
constructor TRODLEnum.Create;
begin
inherited;
fPrefixEnumValues := True;
end;
function TRODLEnum.GetItemClass: TRODLEntityClass;
begin
result := TRODLEnumValue;
end;
function TRODLEnum.GetItems(Index: integer): TRODLEnumValue;
begin
result := TRODLEnumValue(inherited Items[Index]);
end;
procedure TRODLEnum.Validate(iMessages: IRoPluginMessages);
begin
inherited;
if Count = 0 then
iMessages.AddMessage(rmtError,Info.Name,err_RodlNoEnumValues,-1,self);
end;
{ TRODLBaseService }
function TRODLBaseService.Add(aServiceInterface: TRODLServiceInterface): integer;
begin
result := inherited Add(aServiceInterface);
end;
function TRODLBaseService.Add: TRODLServiceInterface;
begin
result := TRODLServiceInterface(inherited Add);
end;
constructor TRODLBaseService.Create;
var
defintf: TRODLServiceInterface;
begin
inherited;
fisPrivate := False;
defintf := Add;
defintf.Info.Name := DefaultIntfName;
defintf.Info.UID := NewGUID;
end;
function TRODLBaseService.GetAncestor: string;
begin
result := fAncestor;
end;
function TRODLBaseService.GetDefault: TRODLServiceInterface;
var
i: integer;
begin
result := nil;
if (Count = 1) then
result := Items[0]
else
for i := 0 to (Count - 1) do
if (CompareText(Items[i].Info.name, DefaultIntfName) = 0) then begin
result := Items[i];
Exit;
end;
end;
function TRODLBaseService.GetItemClass: TRODLEntityClass;
begin
result := TRODLServiceInterface;
end;
function TRODLBaseService.GetItems(Index: integer): TRODLServiceInterface;
begin
result := TRODLServiceInterface(inherited Items[Index]);
end;
procedure TRODLBaseService.SetAncestor(const Value: string);
begin
fAncestor := Trim(Value);
end;
procedure TRODLBaseService.Validate(iMessages: IRoPluginMessages);
var
i:integer;
begin
inherited;
for i := 0 to Count-1 do begin
//Items[i].Validate(iMessages);
if (Items[i].Count = 0) and (Ancestor = '') then
iMessages.AddMessage(rmtWarning,Info.Name+'.'+Items[i].Info.Name,err_RodlNoOperationsDefined,-1,self);
end;
if (Ancestor <> '') then begin
if self is TRODLEventSink then begin
if not OwnerLibrary.IsValidEventSink(Ancestor) then
iMessages.AddMessage(rmtError,Info.Name,Format(err_RodlInvalidAncestorType,[Ancestor]),-1,self);
end else begin
if not OwnerLibrary.IsValidService(Ancestor) then
iMessages.AddMessage(rmtError,Info.Name,Format(err_RodlInvalidAncestorType,[Ancestor]),-1,self);
end;
end;
end;
{ TRODLOperationParam }
{constructor TRODLOperationParam.Create(const aName, aTypeName: string; aFlag: TRODLParamFlag; aOwner:TRODLEntity);
begin
inherited Create(aName, aTypeName, aOwner);
Flag := aFlag;
end;}
function TRODLOperationParam.GetFlag: string;
begin
result := RODLParamFlagNames[fFlag];
end;
procedure TRODLOperationParam.SetFlag(const aValue: string);
var
lFlag: TRODLParamFlag;
begin
for lFlag := Low(TRODLParamFlag) to High(TRODLParamFlag) do
if SameText(RODLParamFlagNames[lFlag], aValue) then begin
fFlag := lFlag;
exit;
end;
RaiseError(err_InvalidParamFlag, [aValue]);
end;
{ TRODLOperation }
function TRODLOperation.Add(aParam: TRODLOperationParam): integer;
begin
if aParam.fFlag = fResult then
RaiseError(err_MayNotAddResult);
result := inherited Add(aParam)
end;
function TRODLOperation.Add: TRODLOperationParam;
begin
result := TRODLOperationParam(inherited Add);
result.Info.Name := 'Param' + IntToStr(Count);
end;
function TRODLOperation.GetItemClass: TRODLEntityClass;
begin
result := TRODLOperationParam;
end;
function TRODLOperation.GetItems(Index: integer): TRODLOperationParam;
begin
result := TRODLOperationParam(inherited Items[Index]);
end;
function TRODLOperation.GetResult: TRODLOperationParam;
{var
i: integer;}
begin
result := fOperationResult;
{result := nil;
for i := 0 to (Count - 1) do
if (Items[i].Info.Flag = fResult) then begin
result := Items[i];
Exit;
end;}
end;
{ Makes sure the Result patrameter is always at the top of the list, so it
doesn't get in the way of sorting methods. }
{procedure TRODLOperation.MoveResult;
var
i: integer;
begin
for i := 0 to (Count - 1) do
if (Items[i].Info.Flag = fResult) then begin
if i <> 0 then fItems.Move(i,0);
Exit;
end;
end;}
function TRODLOperation.GetCodeBody(iLanguage: string): TStrings;
var
lIndex:integer;
begin
result := nil;
lIndex := fCodeBodies.IndexOf(iLanguage);
if lIndex > -1 then result := fCodeBodies.Objects[lIndex] as TStrings
end;
procedure TRODLOperation.SetCodeBody(iLanguage: string; Value: TStrings);
var
lStrings:TStrings;
lIndex:integer;
begin
if Assigned(Value) then begin
lStrings := GetCodeBody(iLanguage);
if not Assigned(lStrings) then begin
lStrings := TStringList.Create();
fCodeBodies.AddObject(Lowercase(iLanguage),lStrings);
end;
lStrings.Assign(Value);
end
else begin
lIndex := fCodeBodies.IndexOf(iLanguage);
if lIndex > 0 then fCodeBodies.Delete(lIndex);
end;
end;
procedure TRODLOperation.SetCodeBodyAsString(iLanguage: string; const Value: string);
var
lStrings:TStrings;
lIndex:integer;
begin
if Value <> '' then begin
lStrings := GetCodeBody(iLanguage);
if not Assigned(lStrings) then begin
lStrings := TStringList.Create();
fCodeBodies.AddObject(Lowercase(iLanguage),lStrings);
end;
lStrings.Text := Value;
end
else begin
lIndex := fCodeBodies.IndexOf(iLanguage);
if lIndex > 0 then fCodeBodies.Delete(lIndex);
end;
end;
constructor TRODLOperation.Create;
begin
inherited;
fCodeBodies := TStringList.Create();
fCodeBodies.Sorted := true;
fCodeBodies.Duplicates := dupError;
end;
destructor TRODLOperation.Destroy;
var i:integer;
begin
RemoveResult;
for i := 0 to fCodeBodies.Count-1 do fCodeBodies.Objects[i].Free();
FreeAndNil(fCodeBodies);
inherited;
end;
function TRODLOperation.GetCodeBodyCount: integer;
begin
result := fCodeBodies.Count;
end;
function TRODLOperation.GetCodeBodyLanguages(iIndex: integer): string;
begin
result := fCodeBodies[iIndex];
end;
{procedure TRODLOperation.Exchange(Index1, Index2: integer);
begin
MoveResult();
if Assigned(GetResult()) then begin
inc(Index1);
inc(Index2);
end;
inherited Exchange(Index1, Index2);
end;}
function TRODLOperation.AddResult: TRODLOperationParam;
begin
if not Assigned(fOperationResult) then begin
fOperationResult := TRODLOperationParam.Create;
fOperationResult.fOwner := self;
fOperationResult.Flag := fResult;
fOperationResult.Name := 'Result';
end;
result := fOperationResult;
end;
procedure TRODLOperation.RemoveResult;
begin
if Assigned(fOperationResult) then
FreeAndNil(fOperationResult);
end;
function TRODLOperation.GetParameter(const aParameterName: string): TRODLOperationParam;
begin
result := TRODLOperationParam(ItemByName(aParameterName));
if result=NIL then raise EROUnknownItem.CreateFmt('Cannot find parameter %s', [aParameterName]);
end;
procedure TRODLOperation.Validate(iMessages: IROPluginMessages);
begin
inherited;
if (Result <> nil) and (Result.DataType <> '') then begin
if not Owner.OwnerLibrary.IsValidType(Result.DataType) then
iMessages.AddMessage(rmtError,Info.Name+'.'+Name,Format(err_RodlInvalidDataType,[Result.DataType]),-1,Self);
end;
end;
{ TRODLServiceInterface }
function TRODLServiceInterface.Add(aParam: TRODLOperation): integer;
begin
result := inherited Add(aParam)
end;
function TRODLServiceInterface.Add: TRODLOperation;
begin
result := TRODLOperation(inherited Add);
result.Info.Name := 'Operation' + IntToStr(Count);
result.Info.UID := NewGUID;
end;
function TRODLServiceInterface.GetOperation(
const anOperationName: string;
IncludeAnchestors : boolean = FALSE) : TRODLOperation;
begin
result := FindOperation(anOperationName, IncludeAnchestors);
if (result=NIL) then raise EROUnknownItem.CreateFmt('Cannot find operation %s', [anOperationName]);
end;
procedure TRODLServiceInterface.GetOperationsList(AList: TList);
var svc : TRODLService;
i: Integer;
lib : TRODLLibrary;
begin
AList.Clear;
For i:=0 to Count-1 do
AList.Add(Items[i]);
lib := info.Owner.OwnerLibrary;
svc := lib.FindService((Owner as TRODLService).Info.Name);
while TRUE do begin
if (svc.Ancestor='') then Break;
svc := lib.GetService(svc.Ancestor);
For i:=0 to Count-1 do
AList.Add(svc.Default.Items[i]);
end;
end;
function TRODLServiceInterface.GetItemClass: TRODLEntityClass;
begin
result := TRODLOperation;
end;
function TRODLServiceInterface.GetItems(Index: integer): TRODLOperation;
begin
result := TRODLOperation(inherited Items[Index]);
end;
function TRODLServiceInterface.FindOperation(const anOperationName : string; IncludeAnchestors : boolean = FALSE) : TRODLOperation;
var svc : TRODLService;
i: Integer;
lib : TRODLLibrary;
begin
result := NIL;
for i := 0 to (Count-1) do
if SameText(anOperationName, Items[i].Info.Name) then begin
result := Items[i];
Exit;
end;
if (result=NIL) and IncludeAnchestors then begin
lib := info.Owner.OwnerLibrary;
//intf := TRODLServiceInterface;
svc := lib.FindService((Owner as TRODLService).Info.Name);
while TRUE do begin
if (svc.Ancestor='') then Break;
svc := lib.GetService(svc.Ancestor);
result := svc.Default.FindOperation(anOperationName);
if (result<>NIL) then Exit;
end;
end;
end;
{ TRODLLibrary }
function TRODLLibrary.Add(anEntity: TRODLEntity): integer;
begin
if (anEntity is TRODLArray) then
Inc(fArrayCount)
else if (anEntity is TRODLEnum) then
Inc(fEnumCount)
else if (anEntity is TRODLStruct) then
Inc(fStructCount)
else if (anEntity is TRODLService) then
Inc(fServiceCount)
else if (anEntity is TRODLUse) then
Inc(fUseCount)
else if (anEntity is TRODLException) then
Inc(fExceptionCount)
else if (anEntity is TRODLEventSink) then
Inc(fEventSinkCount)
else if (anEntity is TRODLGroup) then
Inc(fGroupCount);
result := inherited Add(anEntity);
end;
function TRODLLibrary.GetItemClass: TRODLEntityClass;
begin
result := TRODLEntity;
end;
procedure TRODLLibrary.Remove(anEntity: TRODLEntity);
var
i: Integer;
begin
if (anEntity is TRODLGroup) then begin
for i := 0 to Count-1 do
if Items[i].GroupUnder = anEntity then
Items[i].GroupUnder := anEntity.GroupUnder;
end
else if (anEntity is TRODLUse) then begin
for i := Count-1 downto 0 do
if Items[i].LocatedInRodlUse = anEntity then
Remove(Items[i]);
end;
if (anEntity is TRODLArray) then
Dec(fArrayCount)
else if (anEntity is TRODLEnum) then
Dec(fEnumCount)
else if (anEntity is TRODLStruct) then
Dec(fStructCount)
else if (anEntity is TRODLService) then
Dec(fServiceCount)
else if (anEntity is TRODLUse) then
Dec(fUseCount)
else if (anEntity is TRODLException) then
Dec(fExceptionCount)
else if (anEntity is TRODLEventSink) then
Dec(fEventSinkCount)
else if (anEntity is TRODLGroup) then
Dec(fGroupCount);
inherited;
end;
procedure TRODLLibrary.Delete(Index: integer);
var
item: TRODLEntity;
begin
item := Items[Index];
Remove(item);
inherited Delete(Index);
end;
function TRODLLibrary.GetArray(Index: integer): TRODLArray;
begin
if (Index > ArrayCount - 1) then RaiseError(err_InvalidIndex, [Index]);
result := GetByType(Index,TRODLArray) as TRODLArray;
end;
function TRODLLibrary.GetEnums(Index: integer): TRODLEnum;
begin
if (Index > EnumCount - 1) then RaiseError(err_InvalidIndex, [Index]);
result := GetByType(Index,TRODLEnum) as TRODLEnum;
end;
function TRODLLibrary.GetServices(Index: integer): TRODLService;
begin
if (Index > ServiceCount - 1) then RaiseError(err_InvalidIndex, [Index]);
result := GetByType(Index,TRODLService) as TRODLService;
end;
function TRODLLibrary.GetStructs(Index: integer): TRODLStruct;
begin
if (Index > StructCount - 1) then RaiseError(err_InvalidIndex, [Index]);
result := GetByType(Index,TRODLStruct) as TRODLStruct;
end;
function TRODLLibrary.GetExceptions(Index: integer): TRODLException;
begin
if (Index > ExceptionCount - 1) then RaiseError(err_InvalidIndex, [Index]);
result := GetByType(Index,TRODLException) as TRODLException;
end;
function TRODLLibrary.GetUse(Index: integer): TRODLUse;
begin
if (Index > UseCount - 1) then RaiseError(err_InvalidIndex, [Index]);
result := GetByType(Index,TRODLUse) as TRODLUse;
end;
function TRODLLibrary.GetGroups(Index: integer): TRODLGroup;
begin
if (Index > GroupCount - 1) then RaiseError(err_InvalidIndex, [Index]);
result := GetByType(Index,TRODLGroup) as TRODLGroup;
end;
function TRODLLibrary.GetEventSinks(Index: integer): TRODLEventSink;
begin
if (Index > EventSinkCount - 1) then RaiseError(err_InvalidIndex, [Index]);
result := GetByType(Index,TRODLEventSink) as TRODLEventSink;
end;
function TRODLLibrary.GetByType(aIndex:integer; aType:TRODLEntityClass):TRODLEntity;
var
i, c: integer;
begin
result := nil;
if (aIndex < 0) then RaiseError(err_InvalidIndex, [aIndex]);
c := -1;
for i := 0 to (Count - 1) do begin
if (Items[i] is aType) then Inc(c);
if (c = aIndex) then begin
result := Items[i];
Exit;
end;
end;
end;
constructor TRODLLibrary.Create;
begin
inherited;
Info.Name := 'NewLibrary';
Info.UID := NewGUID;
end;
function TRODLLibrary.IsValidCustomType(const iTypeName: string): boolean;
var
i:integer;
begin
result := false;
for i := 0 to ArrayCount-1 do begin
if CompareText(Arrays[i].Info.Name,iTypeName) = 0 then begin
result := true;
exit;
end;
end;
for i := 0 to StructCount-1 do begin
if CompareText(Structs[i].Info.Name,iTypeName) = 0 then begin
result := true;
exit;
end;
end;
for i := 0 to EnumCount-1 do begin
if CompareText(Enums[i].Info.Name,iTypeName) = 0 then begin
result := true;
exit;
end;
end;
end;
function TRODLLibrary.IsValidSimpleType(const iTypeName: string): boolean;
var
d:TRODataType;
i: Integer;
begin
result := false;
for d := Low(TRODataType) to High(TRODataType) do begin
if (not (d in [rtUserDefined])) and
(CompareText(DataTypeNames[d],iTypeName) = 0) then begin
result := true;
exit;
end;
end;
for i := Low(DataTypeRemapping) to High(DataTypeRemapping) do begin
if CompareText(DataTypeRemapping[i].Name, iTypeName) = 0 then begin
result := true;
exit;
end;
end;
end;
function TRODLLibrary.IsValidType(const iTypeName: string): boolean;
begin
result := IsValidCustomType(iTypeName) or IsValidSimpleType(iTypeName);
end;
function TRODLLibrary.FindStruct(const iStructName: string): TRODLStruct;
var
i:integer;
begin
result := nil;
for i := 0 to StructCount-1 do begin
if CompareText(Structs[i].Info.Name,iStructName) = 0 then begin
result := Structs[i];
exit;
end;
end;
end;
function TRODLLibrary.FindBaseStruct(const iStructName: string): TRODLBaseStruct;
var
i:integer;
begin
result := nil;
for i := 0 to Count-1 do begin
if (Items[i] is TRODLBaseStruct) and (CompareText(Items[i].Info.Name,iStructName) = 0) then begin
result := Items[i] as TRODLBaseStruct;
exit;
end;
end;
end;
function TRODLLibrary.FindEnum(const iEnumName: string): TRODLEnum;
var
i:integer;
begin
result := nil;
for i := 0 to EnumCount-1 do begin
if CompareText(Enums[i].Info.Name,iEnumName) = 0 then begin
result := Enums[i];
exit;
end;
end;
end;
function TRODLLibrary.FindArray(const iArrayName: string): TRODLArray;
var
i:integer;
begin
result := nil;
for i := 0 to ArrayCount-1 do begin
if CompareText(Arrays[i].Info.Name,iArrayName) = 0 then begin
result := Arrays[i];
exit;
end;
end;
end;
function TRODLLibrary.FindGroup(const aID: TGUID): TRODLGroup;
var
i:integer;
begin
result := nil;
for i := 0 to GroupCount-1 do begin
if IsEqualGUID(Groups[i].UID,aID) then begin
result := Groups[i];
exit;
end;
end;
end;
function TRODLLibrary.IsValidService(const iServiceName: string): boolean;
var
i:integer;
begin
result := false;
for i := 0 to ServiceCount-1 do begin
if CompareText(Services[i].Info.Name,iServiceName) = 0 then begin
result := true;
exit;
end;
end;
end;
function TRODLLibrary.FindService(const iServiceName: string):TRODLService;
var
i:integer;
begin
result := nil;
for i := 0 to ServiceCount-1 do begin
if CompareText(Services[i].Info.Name,iServiceName) = 0 then begin
result := Services[i];
exit;
end;
end;
end;
function TRODLLibrary.FindException(const iExceptionName: string):TRODLException;
var
i:integer;
begin
result := nil;
for i := 0 to ExceptionCount-1 do begin
if CompareText(Exceptions[i].Info.Name,iExceptionName) = 0 then begin
result := Exceptions[i];
exit;
end;
end;
end;
function TRODLLibrary.FindUse(const iUseName: string):TRODLUse;
var
i:integer;
begin
result := nil;
for i := 0 to fUseCount-1 do begin
if CompareText(Use[i].Info.Name,iUseName) = 0 then begin
result := Use[i];
exit;
end;
end;
end;
function TRODLLibrary.FindUseByFilename(const iUseRODLFile: string):TRODLUse;
var
i:integer;
begin
result := nil;
for i := 0 to fUseCount-1 do begin
if CompareText(Use[i].RodlFile, iUseRODLFile) = 0 then begin
result := Use[i];
exit;
end;
end;
end;
function TRODLLibrary.IsValidException(const iTypeName:string):boolean;
var
i:integer;
begin
result := false;
for i := 0 to ExceptionCount-1 do begin
if CompareText(Exceptions[i].Info.Name,iTypeName) = 0 then begin
result := true;
exit;
end;
end;
end;
function TRODLLibrary.CalcServiceOrder: IROStrings;
var
lEntities:IROStrings;
i:integer;
begin
lEntities := NewROStrings();
for i := ServiceCount-1 downto 0 do begin
if not Services[i].IsFromUsedRodl then
lEntities.AddObject(Services[i].Info.Name,Services[i])
end;
result := CalcOrder(lEntities);
end;
function TRODLLibrary.CalcEventSinkOrder: IROStrings;
var
lEntities:IROStrings;
i:integer;
begin
lEntities := NewROStrings();
for i := EventSinkCount-1 downto 0 do begin
if not EventSinks[i].IsFromUsedRodl then
lEntities.AddObject(EventSinks[i].Info.Name,EventSinks[i])
end;
result := CalcOrder(lEntities);
end;
function TRODLLibrary.CalcStructOrder: IROStrings;
var
lEntities:IROStrings;
i:integer;
begin
lEntities := NewROStrings();
for i := StructCount-1 downto 0 do begin
if not Structs[i].IsFromUsedRodl then
lEntities.AddObject(Structs[i].Info.Name,Structs[i])
end;
result := CalcOrder(lEntities);
end;
function TRODLLibrary.CalcExceptionOrder: IROStrings;
var
lEntities:IROStrings;
i:integer;
begin
lEntities := NewROStrings();
for i := ExceptionCount-1 downto 0 do begin
if not Exceptions[i].IsFromUsedRodl then
lEntities.AddObject(Exceptions[i].Info.Name,Exceptions[i])
end;
result := CalcOrder(lEntities);
end;
function TRODLLibrary.CalcOrder(const iObjects:IROStrings):IROStrings;
var
lAncestors:IROStrings;
i,lIndex:integer;
lEntity:TRODLEntity;
lWorked:boolean;
begin
lAncestors := NewROStrings();
result := NewROStrings();
for i := 0 to iObjects.Count-1 do begin
lEntity := iObjects.Objects[i] as TRODLEntity;
lAncestors.AddObject((lEntity as IRODLEntityWithAncestor).Ancestor,lEntity)
end;
for i := lAncestors.Count-1 downto 0 do begin
if lAncestors[i] <> '' then lIndex := iObjects.IndexOf(lAncestors[i]) else lIndex := -1; { else needed to keep the warning away only }
if (lAncestors[i] = '') or (lIndex = -1) then begin
result.AddObject((lAncestors.Objects[i] as TRODLEntity).Info.Name,lAncestors.Objects[i]);
lAncestors.Delete(i);
end;
end;
while lAncestors.Count > 0 do begin
lWorked := false;
for i := lAncestors.Count-1 downto 0 do begin
lIndex := result.IndexOf(lAncestors[i]);
if (lIndex > -1) then begin
result.InsertObject(lIndex+1,(lAncestors.Objects[i] as TRODLEntity).Info.Name,lAncestors.Objects[i]);
lAncestors.Delete(i);
lWorked := true;
end;
end;
if (not lWorked) and (lAncestors.Count > 0) then
RaiseError('Invalid or recursive inheritance for the following entities: '+lAncestors.Text);
end;
end;
function TRODLLibrary.GetService(const aServiceName: string): TRODLService;
begin
result := FindService(aServiceName);
if result=NIL then raise EROUnknownItem.CreateFmt('Cannot find service %s', [aServiceName])
end;
function TRODLLibrary.GetStruct(const aStructName: string): TRODLStruct;
begin
result := FindStruct(aStructName);
if result=NIL then raise EROUnknownItem.CreateFmt('Cannot find struct %s', [aStructName])
end;
procedure TRODLLibrary.ClearDuplicates;
var
lID: string;
lItem: TRODLEntity;
lIDs: TStringList;
i: Integer;
const
EMPTY_GUID = '{00000000-0000-0000-0000-000000000000}';
begin
lIDs := TStringList.Create();
try
lIDs.Duplicates := dupError;
lIDs.Sorted := true;
for i := Count-1 downto 0 do begin
lItem := Items[i];
if (lItem is TRODLUse) then continue; { removing duplicate uses would blow up the order; and they do no harm anyway }
lID := GUIDToString(lItem.UID);
if SameText(lID, EMPTY_GUID) then continue;
if (lIDs.IndexOf(lID) > -1) and (not SameText(lID, EMPTY_GUID)) then begin
{$IFDEF DEBUG_REMOBJECTS_RODL}
DebugServer.Write('Removing duplicate %s %s (%s)',[lItem.ReadableEntityTypeName, lItem.Name, lID]);
{$ENDIF}
Remove(lItem);
end
else begin
lIDs.Add(lID);
end;
end; { for }
finally
lIDs.Free();
end;
end;
procedure TRODLLibrary.GetArraysByElement(const aElementName: string;
AList: TList);
var
i: integer;
begin
AList.Clear;
for i := 0 to ArrayCount-1 do
if CompareText(Arrays[i].ElementType,aElementName) = 0 then
AList.Add(Arrays[i]);
end;
function TRODLLibrary.IsValidEventSink(
const iEventSink: string): boolean;
var
i: integer;
begin
result := false;
for i := 0 to EventSinkCount-1 do begin
if CompareText(EventSinks[i].Info.Name,iEventsink) = 0 then begin
result := true;
exit;
end;
end;
end;
{ TRODLArray }
procedure TRODLArray.SetElementType(const Value: string);
begin
fElementType := Trim(Value);
end;
procedure TRODLArray.Validate(iMessages:IRoPluginMessages);
//function TRODLArray.Validate(out FaultyEntity: TRODLEntity; out ErrorMessage: string): boolean;
begin
inherited;
if (ElementType = '') then
iMessages.AddMessage(rmtError,Info.Name,err_RodlNoDataTypeSpecified,-1,self);
if (ElementType <> '') and not OwnerLibrary.IsValidType(ElementType) then
iMessages.AddMessage(rmtError,Info.Name,Format(err_RodlInvalidDataType,[ElementType]),-1,Owner);
end;
{ TRODLConverter }
constructor TRODLConverter.Create(const aLibraryFile: string; const aTargetEntity: string = '');
var
lLibrary: TRODLLibrary;
begin
with TXMLToRODL.Create(nil) do try
lLibrary := ReadFromFile(aLibraryFile);
try
Self.Create(lLibrary, aTargetEntity);
finally
FreeAndNil(lLibrary);
end;
finally
Free;
end;
end;
constructor TRODLConverter.Create(const aLibrary: TRODLLibrary; const aTargetEntity: string = '');
begin
inherited Create;
fBuffer := TStringList.Create;
if (aLibrary <> nil) then Convert(aLibrary, aTargetEntity);
end;
destructor TRODLConverter.Destroy;
begin
fBuffer.Free;
inherited;
end;
procedure TRODLConverter.Convert(const aLibrary: TRODLLibrary; const aTargetEntity: string = '');
begin
if (aLibrary = nil) then
RaiseError(err_InvalidLibrary, [])
else if (aTargetEntity<>'') and not ValidateTargetEntity(aLibrary, aTargetEntity) then
RaiseError(err_InvalidTargetEntity, [aTargetEntity]);
fTargetEntity := aTargetEntity;
fBuffer.Clear;
IntConvert(aLibrary, aTargetEntity);
end;
function TRODLConverter.GetBuffer: TStrings;
begin
result := fBuffer as TStrings;
end;
function TRODLConverter.ValidateTargetEntity(const aLibrary: TRODLLibrary; const aTargetEntity: string): boolean;
begin
result := aLibrary.FindService(aTargetEntity)<>NIL;
end;
procedure TRODLConverter.Write(const someText: string; Indentation: integer = 0);
var
i: integer;
s: string;
begin
s := '';
for i := 1 to Indentation do
s := s + ' ';
s := s + someText;
fBuffer.Add(s)
end;
procedure TRODLConverter.WriteLines(const someText: string);
begin
fBuffer.Text := fBuffer.Text + someText;
end;
procedure TRODLConverter.WriteEmptyLine;
begin
fBuffer.Add('');
end;
class function TRODLConverter.GetTargetFileName(const aLibrary: TRODLLibrary;
const aTargetEntity: string): string;
begin
result := '';
end;
{ TRODLReader }
constructor TRODLReader.Create;
begin
end;
function TRODLReader.Read(aStream: TStream; const aFilename:string): TRODLLibrary;
begin
if (aStream = nil) then RaiseError(err_InvalidStream, []);
result := IntReadFromStream(aStream, aFilename)
end;
function TRODLReader.ReadFromFile(const aFileName: string): TRODLLibrary;
var
fs: TFileStream;
begin
fs := TFileStream.Create(aFileName, fmOpenRead);
try
result := Read(fs, aFilename)
finally
fs.Free;
end;
end;
{ TRODLException }
procedure TRODLException.Validate(iMessages: IRoPluginMessages);
begin
inherited;
if (Ancestor <> '') and not OwnerLibrary.IsValidException(Ancestor) then
iMessages.AddMessage(rmtError,Info.Name,Format(err_RodlInvalidAncestorType,[Ancestor]),-1,self);
end;
{ TRODLUse }
procedure TRODLUse.Validate(iMessages: IRoPluginMessages);
begin
inherited;
if not (FileExists(ExpandVariables(fRodlFile)) or FileExists(fAbsoluteRodlFile)) then
iMessages.AddMessage(rmtWarning,ExtractFileName(fRodlFile),Format(err_RodlUsedFileDoesNotExist,[ExpandVariables(fRodlFile)]),-1,self);
end;
end.