1
0
mirror of synced 2024-11-14 19:13:50 +00:00
x2xmldatabinding/Units/DelphiXMLDataBindingGenerator.pas

1816 lines
62 KiB
ObjectPascal
Raw Normal View History

2008-02-20 06:52:00 +00:00
unit DelphiXMLDataBindingGenerator;
interface
uses
System.Classes,
System.Generics.Collections,
Xml.XMLSchema,
2008-03-09 20:36:27 +00:00
DelphiXMLDataBindingResources,
2008-02-20 06:52:00 +00:00
XMLDataBindingGenerator,
XMLDataBindingHelpers;
2008-04-14 19:28:57 +00:00
2008-02-20 06:52:00 +00:00
type
2008-04-14 19:20:55 +00:00
TGetFileNameEvent = procedure(Sender: TObject; const SchemaName: String; var Path, FileName: String) of object;
2008-02-20 06:52:00 +00:00
TXMLSchemaList = TList<TXMLDataBindingSchema>;
2008-04-14 19:28:57 +00:00
2008-02-20 06:52:00 +00:00
TDelphiXMLDataBindingGenerator = class(TXMLDataBindingGenerator)
private
FProcessedItems: TList<TXMLDataBindingInterface>;
FUnitNames: TDictionary<TXMLDataBindingSchema, String>;
2008-04-14 19:28:57 +00:00
FHasChecksEmpty: Boolean;
FOnGetFileName: TGetFileNameEvent;
2008-02-20 06:52:00 +00:00
protected
procedure GenerateDataBinding; override;
2008-04-14 19:28:57 +00:00
procedure GenerateOutputFile(ASchemaList: TXMLSchemaList; const ASourceFileName, AUnitName: String);
function GenerateUsesClause(ASchemaList: TXMLSchemaList): String;
2008-02-20 06:52:00 +00:00
2008-03-09 20:36:27 +00:00
function DelphiSafeName(const AName: String): String;
function TranslateItemName(AItem: TXMLDataBindingItem): String; override;
procedure PostProcessItem(ASchema: TXMLDataBindingSchema; AItem: TXMLDataBindingItem); override;
procedure ResolvePropertyNameConflicts(AItem: TXMLDataBindingInterface);
2008-03-09 20:36:27 +00:00
2008-02-20 06:52:00 +00:00
function DoGetFileName(const ASchemaName: String): String;
function GetDataTypeMapping(ADataType: IXMLTypeDef; out ATypeMapping: TTypeMapping): Boolean;
2008-04-14 19:28:57 +00:00
function GetDataTypeName(AProperty: TXMLDataBindingProperty; AInterfaceName: Boolean): String;
2008-02-26 21:53:11 +00:00
function TranslateDataType(ADataType: IXMLTypeDef): String;
function CreateNewGUID: String;
2008-02-26 21:53:11 +00:00
procedure WriteUnitHeader(AWriter: TNamedFormatWriter; const ASourceFileName, AFileName: String);
procedure WriteSection(AWriter: TNamedFormatWriter; ASection: TDelphiXMLSection; ASchemaList: TXMLSchemaList);
procedure WriteDocumentFunctions(AWriter: TNamedFormatWriter; ASection: TDelphiXMLSection; ASchemaList: TXMLSchemaList);
procedure WriteEnumerationConversions(AWriter: TNamedFormatWriter; ASection: TDelphiXMLSection; ASchemaList: TXMLSchemaList);
procedure WriteImplementationUses(AWriter: TNamedFormatWriter; ASchemaList: TXMLSchemaList);
procedure WriteDocumentation(AWriter: TNamedFormatWriter; AItem: TXMLDataBindingItem);
procedure WriteAfterConstruction(AWriter: TNamedFormatWriter; AItem: TXMLDataBindingInterface; ASection: TDelphiXMLSection);
function WriteInlineCollectionFields(AWriter: TNamedFormatWriter; AItem: TXMLDataBindingInterface): Boolean;
procedure WriteSchemaItem(AWriter: TNamedFormatWriter; AItem: TXMLDataBindingItem; ASection: TDelphiXMLSection);
procedure WriteSchemaInterface(AWriter: TNamedFormatWriter; AItem: TXMLDataBindingInterface; ASection: TDelphiXMLSection);
procedure WriteSchemaInterfaceProperties(AWriter: TNamedFormatWriter; AItem: TXMLDataBindingInterface; ASection: TDelphiXMLSection);
function WriteSchemaInterfaceCollectionProperties(AWriter: TNamedFormatWriter; AItem: TXMLDataBindingInterface; ASection: TDelphiXMLSection): Boolean;
function WriteSchemaInterfaceProperty(AWriter: TNamedFormatWriter; AItem: TXMLDataBindingInterface; AProperty: TXMLDataBindingProperty; ASection: TDelphiXMLSection; AMember: TDelphiXMLMember; ANewLine: Boolean): Boolean;
procedure WriteSchemaEnumeration(AWriter: TNamedFormatWriter; AItem: TXMLDataBindingEnumeration; ASection: TDelphiXMLSection);
procedure WriteSchemaEnumerationArray(AWriter: TNamedFormatWriter; AItem: TXMLDataBindingEnumeration);
procedure WriteValidate(AWriter: TNamedFormatWriter; AItem: TXMLDataBindingInterface; ASection: TDelphiXMLSection);
procedure WriteValidateImplementation(AWriter: TNamedFormatWriter; AItem: TXMLDataBindingInterface; AStrict: Boolean);
procedure WriteEnumeratorMethod(AWriter: TNamedFormatWriter; AItem: TXMLDataBindingInterface; ASection: TDelphiXMLSection);
procedure WriteEnumerator(AWriter: TNamedFormatWriter; AItem: TXMLDataBindingInterface; ASection: TDelphiXMLSection);
2008-04-14 19:28:57 +00:00
function GetDelphiNodeType(AProperty: TXMLDataBindingProperty): TDelphiNodeType;
function GetDelphiElementType(ANodeType: TDelphiNodeType): TDelphiElementType;
function DataTypeConversion(const ADestination, ASource: String; ADataType: IXMLTypeDef; AAccessor: TDelphiAccessor; ANodeType: TDelphiNodeType; const ATargetNamespace: string; const ALinesBefore: String = ''): String;
function XMLToNativeDataType(const ADestination, ASource: String; ADataType: IXMLTypeDef; ANodeType: TDelphiNodeType; const ATargetNamespace: string; const ALinesBefore: String = ''): String;
function NativeDataTypeToXML(const ADestination, ASource: String; ADataType: IXMLTypeDef; ANodeType: TDelphiNodeType; const ATargetNamespace: string; const ALinesBefore: String = ''): String;
property ProcessedItems: TList<TXMLDataBindingInterface> read FProcessedItems;
property UnitNames: TDictionary<TXMLDataBindingSchema, String> read FUnitNames;
2008-02-20 06:52:00 +00:00
public
property HasChecksEmpty: Boolean read FHasChecksEmpty write FHasChecksEmpty;
property OnGetFileName: TGetFileNameEvent read FOnGetFileName write FOnGetFileName;
2008-02-20 06:52:00 +00:00
end;
2008-04-14 19:28:57 +00:00
2008-02-20 06:52:00 +00:00
implementation
uses
StrUtils,
SysUtils,
X2UtNamedFormat,
X2Log.Global;
2008-02-20 06:52:00 +00:00
2008-03-09 20:36:27 +00:00
2008-02-20 06:52:00 +00:00
{ TDelphiXMLDataBindingGenerator }
procedure TDelphiXMLDataBindingGenerator.GenerateDataBinding;
2008-04-14 19:28:57 +00:00
var
schemaList: TXMLSchemaList;
schemaIndex: Integer;
schema: TXMLDataBindingSchema;
unitName: String;
2008-02-20 06:52:00 +00:00
begin
schemaList := TXMLSchemaList.Create;
2008-04-14 19:28:57 +00:00
try
case OutputType of
otSingle:
begin
for schemaIndex := 0 to Pred(SchemaCount) do
schemaList.Add(Schemas[schemaIndex]);
unitName := DoGetFileName(Schemas[0].SchemaName);
GenerateOutputFile(schemaList, SourceFileName, unitName);
end;
otMultiple:
begin
FUnitNames := TDictionary<TXMLDataBindingSchema, String>.Create;
2008-04-14 19:28:57 +00:00
try
for schemaIndex := 0 to Pred(SchemaCount) do
begin
schema := Schemas[schemaIndex];
FUnitNames.Add(schema, DoGetFileName(schema.SchemaName));
2008-04-14 19:28:57 +00:00
end;
for schemaIndex := 0 to Pred(SchemaCount) do
begin
schema := Schemas[schemaIndex];
schemaList.Clear;
2008-04-14 19:28:57 +00:00
schemaList.Add(schema);
unitName := FUnitNames[schema];
GenerateOutputFile(schemaList, schema.SourceFileName, unitName);
end;
finally
FreeAndNil(FUnitNames);
end;
end;
end;
finally
FreeAndNil(schemaList);
2008-02-20 06:52:00 +00:00
end;
end;
2008-04-14 19:28:57 +00:00
procedure TDelphiXMLDataBindingGenerator.GenerateOutputFile(ASchemaList: TXMLSchemaList; const ASourceFileName, AUnitName: String);
2008-02-20 06:52:00 +00:00
var
unitWriter: TNamedFormatWriter;
usesClause: String;
2008-02-20 06:52:00 +00:00
begin
2008-04-14 19:28:57 +00:00
usesClause := '';
if OutputType = otMultiple then
usesClause := GenerateUsesClause(ASchemaList);
unitWriter := TNamedFormatWriter.Create(AUnitName, False, TEncoding.ANSI);
2008-02-20 06:52:00 +00:00
try
WriteUnitHeader(unitWriter, ASourceFileName, AUnitName);
unitWriter.WriteNamedFmt(UnitInterface,
2008-04-14 19:28:57 +00:00
['UsesClause', usesClause]);
WriteSection(unitWriter, dxsForward, ASchemaList);
2008-03-09 20:36:27 +00:00
FProcessedItems := TList<TXMLDataBindingInterface>.Create;
2008-03-09 20:36:27 +00:00
try
FProcessedItems.Clear;
WriteSection(unitWriter, dxsInterface, ASchemaList);
FProcessedItems.Clear;
WriteSection(unitWriter, dxsClass, ASchemaList);
2008-03-09 20:36:27 +00:00
finally
FreeAndNil(FProcessedItems);
2008-02-20 06:52:00 +00:00
end;
WriteDocumentFunctions(unitWriter, dxsInterface, ASchemaList);
WriteEnumerationConversions(unitWriter, dxsInterface, ASchemaList);
2008-02-26 21:53:11 +00:00
unitWriter.Write(UnitImplementation);
WriteImplementationUses(unitWriter, ASchemaList);
WriteDocumentFunctions(unitWriter, dxsImplementation, ASchemaList);
WriteEnumerationConversions(unitWriter, dxsImplementation, ASchemaList);
WriteSection(unitWriter, dxsImplementation, ASchemaList);
2008-02-20 06:52:00 +00:00
unitWriter.Write(unitFooter);
2008-02-20 06:52:00 +00:00
finally
FreeAndNil(unitWriter);
2008-02-20 06:52:00 +00:00
end;
end;
2008-04-14 19:28:57 +00:00
function TDelphiXMLDataBindingGenerator.GenerateUsesClause(ASchemaList: TXMLSchemaList): String;
var
includedSchemas: TList<TXMLDataBindingSchema>;
2008-04-14 19:28:57 +00:00
procedure AddSchema(ASchema: TXMLDataBindingSchema);
begin
if Assigned(ASchema) and
(not includedSchemas.Contains(ASchema)) and
(not ASchemaList.Contains(ASchema)) then
2008-04-14 19:28:57 +00:00
includedSchemas.Add(ASchema);
end;
var
schemaIndex: Integer;
schema: TXMLDataBindingSchema;
itemIndex: Integer;
interfaceItem: TXMLDataBindingInterface;
propertyIndex: Integer;
propertyItem: TXMLDataBindingProperty;
2008-02-20 06:52:00 +00:00
begin
2008-04-14 19:28:57 +00:00
Result := '';
includedSchemas := TList<TXMLDataBindingSchema>.Create;
2008-04-14 19:28:57 +00:00
try
{ Determine which items are used }
for schemaIndex := 0 to Pred(ASchemaList.Count) do
begin
schema := ASchemaList[schemaIndex];
for itemIndex := 0 to Pred(schema.ItemCount) do
begin
if schema.Items[itemIndex].ItemType = itInterface then
begin
interfaceItem := TXMLDataBindingInterface(schema.Items[itemIndex]);
if Assigned(interfaceItem.CollectionItem) then
AddSchema(interfaceItem.CollectionItem.Schema);
for propertyIndex := 0 to Pred(interfaceItem.PropertyCount) do
begin
propertyItem := interfaceItem.Properties[propertyIndex];
if propertyItem.PropertyType = ptItem then
AddSchema(TXMLDataBindingItemProperty(propertyItem).Item.Schema);
end;
end;
end;
end;
{ Build uses clause }
if includedSchemas.Count > 0 then
begin
for schema in includedSchemas do
2008-04-14 19:28:57 +00:00
Result := Result + ' ' + ChangeFileExt(ExtractFileName(FUnitNames[schema]), '') + ',' + CrLf;
Result := Result + CrLf;
end;
finally
FreeAndNil(includedSchemas);
end;
2008-02-20 06:52:00 +00:00
end;
function TDelphiXMLDataBindingGenerator.GetDataTypeMapping(ADataType: IXMLTypeDef; out ATypeMapping: TTypeMapping): Boolean;
2008-03-09 20:36:27 +00:00
var
mappingIndex: Integer;
2008-04-14 19:28:57 +00:00
dataTypeName: String;
2008-03-09 20:36:27 +00:00
2008-02-26 21:53:11 +00:00
begin
2008-03-09 20:36:27 +00:00
Assert(not ADataType.IsComplex, 'Complex DataTypes not supported');
Assert(ADataType.Enumerations.Count = 0, 'Enumerations not supported');
Result := False;
2008-02-26 21:53:11 +00:00
2008-03-09 20:36:27 +00:00
if (ADataType.NamespaceURI = SXMLSchemaURI_1999) or
(ADataType.NamespaceURI = SXMLSchemaURI_2000_10) or
(ADataType.NamespaceURI = SXMLSchemaURI_2001) then
2008-02-26 21:53:11 +00:00
begin
2008-03-09 20:36:27 +00:00
dataTypeName := ADataType.Name;
for mappingIndex := Low(SimpleTypeMapping) to High(SimpleTypeMapping) do
if SimpleTypeMapping[mappingIndex].SchemaName = dataTypeName then
2008-03-09 20:36:27 +00:00
begin
ATypeMapping := SimpleTypeMapping[mappingIndex];
Result := True;
2008-03-09 20:36:27 +00:00
Break;
end;
end;
end;
2008-04-14 19:28:57 +00:00
function TDelphiXMLDataBindingGenerator.GetDataTypeName(AProperty: TXMLDataBindingProperty; AInterfaceName: Boolean): String;
var
item: TXMLDataBindingItem;
begin
case AProperty.PropertyType of
ptSimple:
if AProperty.IsRepeating then
begin
if AInterfaceName then
Result := ItemInterface
else
Result := ItemClass;
end else
Result := TranslateDataType(TXMLDataBindingSimpleProperty(AProperty).DataType);
2008-04-14 19:28:57 +00:00
ptItem:
begin
item := TXMLDataBindingItemProperty(AProperty).Item;
if (item.ItemType = itEnumeration) or (not AInterfaceName) then
Result := PrefixClass
else
Result := PrefixInterface;
Result := Result + item.TranslatedName;
end;
end;
end;
function TDelphiXMLDataBindingGenerator.TranslateDataType(ADataType: IXMLTypeDef): String;
var
typeMapping: TTypeMapping;
2008-04-14 19:28:57 +00:00
begin
Result := 'Variant';
if GetDataTypeMapping(ADataType, typeMapping) then
Result := typeMapping.DelphiName;
2008-03-09 20:36:27 +00:00
end;
function TDelphiXMLDataBindingGenerator.DelphiSafeName(const AName: String): String;
var
2008-04-18 14:36:17 +00:00
charIndex: Integer;
2008-03-09 20:36:27 +00:00
wordIndex: Integer;
begin
Result := AName;
2008-04-18 14:36:17 +00:00
{ Remove unsafe characters }
for charIndex := Length(Result) downto 1 do
2008-02-26 21:53:11 +00:00
begin
if not CharInSet(Result[charIndex], SafeChars) then
2008-04-18 14:36:17 +00:00
Delete(Result, charIndex, 1);
end;
if Length(Result) > 0 then
begin
{ Number as the first character is not allowed }
if CharInSet(Result[1], ['0'..'9']) then
2008-03-09 20:36:27 +00:00
Result := '_' + Result;
2008-04-18 14:36:17 +00:00
{ Check for reserved words }
for wordIndex := Low(ReservedWords) to High(ReservedWords) do
begin
if SameText(Result, ReservedWords[wordIndex]) then
2008-04-18 14:36:17 +00:00
begin
Result := '_' + Result;
Break;
end;
2008-02-26 21:53:11 +00:00
end;
end;
end;
2008-03-09 20:36:27 +00:00
function TDelphiXMLDataBindingGenerator.TranslateItemName(AItem: TXMLDataBindingItem): String;
begin
Result := DelphiSafeName(inherited TranslateItemName(AItem));
case AItem.ItemType of
itEnumerationMember:
Result := DelphiSafeName(TXMLDataBindingEnumerationMember(AItem).Enumeration.TranslatedName) + '_' + Result;
2008-03-09 20:36:27 +00:00
end;
end;
procedure TDelphiXMLDataBindingGenerator.PostProcessItem(ASchema: TXMLDataBindingSchema; AItem: TXMLDataBindingItem);
begin
inherited PostProcessItem(ASchema, AItem);
if AItem.ItemType = itInterface then
begin
{ Resolve conflicts in case only for properties }
ResolvePropertyNameConflicts(TXMLDataBindingInterface(AItem));
end;
end;
procedure TDelphiXMLDataBindingGenerator.ResolvePropertyNameConflicts(AItem: TXMLDataBindingInterface);
var
propertyNames: TStringList;
propertyItem: TXMLDataBindingProperty;
propertyIndex: Integer;
baseName: String;
counter: Integer;
begin
propertyNames := TStringList.Create;
try
propertyNames.CaseSensitive := False;
for propertyIndex := 0 to Pred(AItem.PropertyCount) do
begin
propertyItem := AItem.Properties[propertyIndex];
baseName := propertyItem.TranslatedName;
counter := 1;
while propertyNames.IndexOf(propertyItem.TranslatedName) > -1 do
begin
{ Unfortunately, the context is exactly the same, this is the best we can do }
Inc(counter);
propertyItem.TranslatedName := baseName + IntToStr(counter);
end;
propertyNames.Add(propertyItem.TranslatedName);
end;
finally
FreeAndNil(propertyNames);
end;
end;
procedure TDelphiXMLDataBindingGenerator.WriteUnitHeader(AWriter: TNamedFormatWriter; const ASourceFileName, AFileName: String);
2008-02-20 06:52:00 +00:00
begin
AWriter.WriteNamedFmt(UnitHeader,
2008-04-14 19:28:57 +00:00
['SourceFileName', ASourceFileName,
'UnitName', ChangeFileExt(ExtractFileName(AFileName), ''),
'DateTime', DateTimeToStr(Now)]);
2008-03-09 20:36:27 +00:00
end;
procedure TDelphiXMLDataBindingGenerator.WriteSection(AWriter: TNamedFormatWriter; ASection: TDelphiXMLSection; ASchemaList: TXMLSchemaList);
2008-03-09 20:36:27 +00:00
var
schemaIndex: Integer;
schema: TXMLDataBindingSchema;
itemIndex: Integer;
begin
2008-04-14 19:28:57 +00:00
for schemaIndex := 0 to Pred(ASchemaList.Count) do
2008-03-09 20:36:27 +00:00
begin
2008-04-14 19:28:57 +00:00
schema := ASchemaList[schemaIndex];
AWriter.WriteLineNamedFmt(SectionComments[ASection],
['SchemaName', schema.SchemaName]);
2008-03-09 20:36:27 +00:00
for itemIndex := 0 to Pred(schema.ItemCount) do
WriteSchemaItem(AWriter, schema.Items[itemIndex], ASection);
2008-03-09 20:36:27 +00:00
AWriter.WriteLine;
2008-03-09 20:36:27 +00:00
end;
end;
procedure TDelphiXMLDataBindingGenerator.WriteDocumentFunctions(AWriter: TNamedFormatWriter; ASection: TDelphiXMLSection; ASchemaList: TXMLSchemaList);
2008-03-09 20:36:27 +00:00
var
schemaIndex: Integer;
schema: TXMLDataBindingSchema;
itemIndex: Integer;
item: TXMLDataBindingItem;
interfaceItem: TXMLDataBindingInterface;
hasItem: Boolean;
nameSpace: String;
2008-03-09 20:36:27 +00:00
begin
hasItem := False;
nameSpace := '';
2008-03-09 20:36:27 +00:00
2008-04-14 19:28:57 +00:00
for schemaIndex := 0 to Pred(ASchemaList.Count) do
2008-02-20 06:52:00 +00:00
begin
2008-04-14 19:28:57 +00:00
schema := ASchemaList[schemaIndex];
2008-03-09 20:36:27 +00:00
for itemIndex := 0 to Pred(schema.ItemCount) do
2008-02-20 06:52:00 +00:00
begin
2008-03-09 20:36:27 +00:00
item := schema.Items[itemIndex];
2008-02-20 06:52:00 +00:00
2008-03-09 20:36:27 +00:00
if item.ItemType = itInterface then
2008-02-20 06:52:00 +00:00
begin
2008-03-09 20:36:27 +00:00
interfaceItem := TXMLDataBindingInterface(item);
if item.DocumentElement then
2008-02-26 21:53:11 +00:00
begin
2008-03-09 20:36:27 +00:00
if not hasItem then
begin
if ASection = dxsInterface then
AWriter.Write(' ');
2008-03-17 12:17:55 +00:00
AWriter.WriteLine('{ Document functions }');
2008-03-09 20:36:27 +00:00
hasItem := True;
end;
if Length(schema.TargetNamespace) > 0 then
nameSpace := schema.TargetNamespace;
with TNamedFormatStringList.Create do
2008-03-17 12:17:55 +00:00
try
case ASection of
dxsInterface: Add(DocumentFunctionsInterface);
dxsImplementation: Add(DocumentFunctionsImplementation);
2008-03-17 12:17:55 +00:00
end;
2008-03-09 20:36:27 +00:00
AWriter.Write(Format(['SourceName', interfaceItem.Name,
'Name', interfaceItem.TranslatedName]));
2008-03-17 12:17:55 +00:00
finally
Free;
2008-03-17 12:17:55 +00:00
end;
2008-03-09 20:36:27 +00:00
AWriter.WriteLine;
2008-02-26 21:53:11 +00:00
end;
end;
2008-02-20 06:52:00 +00:00
end;
end;
if (ASection = dxsInterface) and hasItem then
2008-03-09 20:36:27 +00:00
begin
AWriter.WriteLine('const');
AWriter.WriteLine(' TargetNamespace = ''%s'';', [nameSpace]);
AWriter.WriteLine;
AWriter.WriteLine;
2008-03-09 20:36:27 +00:00
end;
end;
procedure TDelphiXMLDataBindingGenerator.WriteEnumerationConversions(AWriter: TNamedFormatWriter; ASection: TDelphiXMLSection; ASchemaList: TXMLSchemaList);
2008-02-20 06:52:00 +00:00
var
enumerations: TList<TXMLDataBindingItem>;
2008-04-14 19:28:57 +00:00
schemaIndex: Integer;
schema: TXMLDataBindingSchema;
itemIndex: Integer;
item: TXMLDataBindingItem;
enumerationItem: TXMLDataBindingEnumeration;
sourceCode: TNamedFormatStringList;
indent: String;
2008-02-20 06:52:00 +00:00
begin
2008-04-14 19:28:57 +00:00
if not (ASection in [dxsInterface, dxsImplementation]) then
Exit;
enumerations := TList<TXMLDataBindingItem>.Create;
try
2008-04-14 19:28:57 +00:00
for schemaIndex := 0 to Pred(ASchemaList.Count) do
2008-02-20 06:52:00 +00:00
begin
2008-04-14 19:28:57 +00:00
schema := ASchemaList[schemaIndex];
2008-03-09 20:36:27 +00:00
for itemIndex := 0 to Pred(schema.ItemCount) do
2008-02-26 21:53:11 +00:00
begin
item := schema.Items[itemIndex];
2008-03-09 20:36:27 +00:00
if item.ItemType = itEnumeration then
enumerations.Add(item);
2008-02-26 21:53:11 +00:00
end;
2008-02-20 06:52:00 +00:00
end;
2008-04-14 19:28:57 +00:00
if enumerations.Count > 0 then
begin
2008-04-14 19:28:57 +00:00
if ASection = dxsInterface then
begin
{ Enumeration value arrays }
AWriter.WriteLine('const');
2008-04-14 19:28:57 +00:00
for itemIndex := 0 to Pred(enumerations.Count) do
WriteSchemaEnumerationArray(AWriter, TXMLDataBindingEnumeration(enumerations[itemIndex]));
2008-04-14 19:28:57 +00:00
end;
{ Conversion helpers }
if ASection = dxsInterface then
AWriter.Write(' ');
2008-04-14 19:28:57 +00:00
AWriter.WriteLine('{ Enumeration conversion helpers }');
2008-04-14 19:28:57 +00:00
for itemIndex := Pred(enumerations.Count) downto 0 do
begin
enumerationItem := TXMLDataBindingEnumeration(enumerations[itemIndex]);
indent := '';
if ASection = dxsInterface then
indent := ' ';
sourceCode := TNamedFormatStringList.Create;
2008-04-14 19:28:57 +00:00
try
sourceCode.Add(indent + 'function StringTo%<ItemName>:s(const AValue: WideString): %<DataType>:s;');
if ASection = dxsImplementation then
begin
sourceCode.Add('var');
sourceCode.Add(' enumValue: %<DataType>:s;');
sourceCode.AddLn;
sourceCode.Add('begin');
sourceCode.Add(' Result := %<DataType>:s(-1);');
sourceCode.Add(' for enumValue := Low(%<DataType>:s) to High(%<DataType>:s) do');
sourceCode.Add(' if %<ItemName>:sValues[enumValue] = AValue then');
sourceCode.Add(' begin');
sourceCode.Add(' Result := enumValue;');
sourceCode.Add(' break;');
sourceCode.Add(' end;');
sourceCode.Add('end;');
sourceCode.AddLn;
end;
AWriter.Write(sourceCode.Format(['ItemName', enumerationItem.TranslatedName,
2008-04-14 19:28:57 +00:00
'DataType', PrefixClass + enumerationItem.TranslatedName]));
finally
FreeAndNil(sourceCode);
end;
end;
AWriter.WriteLine;
end;
finally
FreeAndNil(enumerations);
2008-02-20 06:52:00 +00:00
end;
2008-03-09 20:36:27 +00:00
end;
2008-02-20 06:52:00 +00:00
procedure TDelphiXMLDataBindingGenerator.WriteImplementationUses(AWriter: TNamedFormatWriter; ASchemaList: TXMLSchemaList);
begin
{ In ye olde days this is where we checked if XMLDataBindingUtils was required. With the
introduction of the IXSDValidate, this is practically always the case. }
AWriter.WriteLine('uses');
AWriter.WriteLine(' Variants;');
AWriter.WriteLine;
end;
procedure TDelphiXMLDataBindingGenerator.WriteDocumentation(AWriter: TNamedFormatWriter; AItem: TXMLDataBindingItem);
2008-03-09 20:36:27 +00:00
var
2008-04-14 19:28:57 +00:00
documentation: String;
lineIndex: Integer;
lines: TStringList;
2008-03-09 20:36:27 +00:00
begin
if not AItem.HasDocumentation then
exit;
lines := TStringList.Create;
2008-03-09 20:36:27 +00:00
try
2008-04-14 19:28:57 +00:00
documentation := AItem.Documentation;
{ Replace dangerous characters }
documentation := StringReplace(documentation, '{', '(', [rfReplaceAll]);
documentation := StringReplace(documentation, '}', ')', [rfReplaceAll]);
lines.Text := WrapText(documentation, 76);
2008-03-09 20:36:27 +00:00
AWriter.WriteLine(' {');
2008-03-09 20:36:27 +00:00
for lineIndex := 0 to Pred(lines.Count) do
AWriter.WriteLine(' ' + lines[lineIndex]);
2008-03-09 20:36:27 +00:00
AWriter.WriteLine(' }');
2008-03-09 20:36:27 +00:00
finally
FreeAndNil(lines);
end;
end;
2008-02-26 21:53:11 +00:00
2008-02-20 06:52:00 +00:00
procedure TDelphiXMLDataBindingGenerator.WriteSchemaItem(AWriter: TNamedFormatWriter; AItem: TXMLDataBindingItem; ASection: TDelphiXMLSection);
2008-03-09 20:36:27 +00:00
begin
case AItem.ItemType of
itInterface: WriteSchemaInterface(AWriter, TXMLDataBindingInterface(AItem), ASection);
itEnumeration: WriteSchemaEnumeration(AWriter, TXMLDataBindingEnumeration(AItem), ASection);
2008-02-20 06:52:00 +00:00
end;
end;
procedure TDelphiXMLDataBindingGenerator.WriteSchemaInterface(AWriter: TNamedFormatWriter; AItem: TXMLDataBindingInterface; ASection: TDelphiXMLSection);
2008-03-09 20:36:27 +00:00
var
parent: String;
2008-02-20 06:52:00 +00:00
begin
2008-03-09 20:36:27 +00:00
if ASection in [dxsInterface, dxsClass] then
begin
{ Ensure the base item is completely defined first, Delphi doesn't allow
inheritance with just a forward declaration. }
if ProcessedItems.Contains(AItem) then
2008-03-09 20:36:27 +00:00
exit;
if Assigned(AItem.BaseItem) then
WriteSchemaInterface(AWriter, AItem.BaseItem, ASection);
2008-03-09 20:36:27 +00:00
ProcessedItems.Add(AItem);
2008-03-09 20:36:27 +00:00
end;
2008-02-26 21:53:11 +00:00
case ASection of
dxsForward:
AWriter.WriteLineNamedFmt(InterfaceItemForward,
['Name', AItem.TranslatedName]);
2008-04-14 19:28:57 +00:00
2008-02-26 21:53:11 +00:00
dxsInterface:
begin
2008-03-09 20:36:27 +00:00
if Assigned(AItem.BaseItem) then
2008-03-17 12:17:55 +00:00
parent := PrefixInterface + AItem.BaseItem.TranslatedName
2008-04-14 19:28:57 +00:00
else if AItem.IsCollection then
begin
parent := CollectionInterface;
WriteEnumerator(AWriter, AItem, ASection);
end else
2008-03-09 20:36:27 +00:00
parent := ItemInterface;
2008-04-14 19:28:57 +00:00
WriteDocumentation(AWriter, AItem);
AWriter.WriteLineNamedFmt(InterfaceItemInterface,
['Name', AItem.TranslatedName,
'ParentName', parent]);
AWriter.WriteLine(' ' + CreateNewGUID);
2008-03-09 20:36:27 +00:00
WriteSchemaInterfaceProperties(AWriter, AItem, ASection);
2008-03-09 20:36:27 +00:00
AWriter.WriteLine(' end;');
AWriter.WriteLine;
2008-02-26 21:53:11 +00:00
end;
2008-04-14 19:28:57 +00:00
2008-02-26 21:53:11 +00:00
dxsClass:
begin
2008-03-09 20:36:27 +00:00
if Assigned(AItem.BaseItem) then
2008-03-17 12:17:55 +00:00
parent := PrefixClass + AItem.BaseItem.TranslatedName
2008-04-14 19:28:57 +00:00
else if AItem.IsCollection then
begin
parent := CollectionClass;
WriteEnumerator(AWriter, AItem, ASection);
end else
2008-03-09 20:36:27 +00:00
parent := ItemClass;
2008-04-14 19:28:57 +00:00
if AItem.CanValidate then
parent := parent + ', ' + XSDValidateInterface;
AWriter.WriteLineNamedFmt(InterfaceItemClass,
['Name', AItem.TranslatedName,
'ParentName', parent]);
2008-03-09 20:36:27 +00:00
WriteSchemaInterfaceProperties(AWriter, AItem, ASection);
2008-03-09 20:36:27 +00:00
AWriter.WriteLine(' end;');
AWriter.WriteLine;
2008-02-26 21:53:11 +00:00
end;
2008-04-14 19:28:57 +00:00
2008-02-26 21:53:11 +00:00
dxsImplementation:
begin
WriteEnumerator(AWriter, AItem, ASection);
WriteSchemaInterfaceProperties(AWriter, AItem, ASection);
2008-02-26 21:53:11 +00:00
end;
end;
end;
procedure TDelphiXMLDataBindingGenerator.WriteAfterConstruction(AWriter: TNamedFormatWriter; AItem: TXMLDataBindingInterface; ASection: TDelphiXMLSection);
2008-04-14 19:28:57 +00:00
var
hasPrototype: Boolean;
2008-03-09 20:36:27 +00:00
procedure WritePrototype;
2008-03-09 20:36:27 +00:00
begin
2008-04-14 19:28:57 +00:00
if not hasPrototype then
2008-03-09 20:36:27 +00:00
begin
2008-04-14 19:28:57 +00:00
case ASection of
dxsClass:
begin
AWriter.WriteLine(' public');
AWriter.WriteLine(' procedure AfterConstruction; override;');
2008-04-14 19:28:57 +00:00
end;
2008-03-09 20:36:27 +00:00
2008-04-14 19:28:57 +00:00
dxsImplementation:
begin
AWriter.WriteLine('procedure TXML%s.AfterConstruction;', [AItem.TranslatedName]);
AWriter.WriteLine('begin');
2008-03-09 20:36:27 +00:00
end;
end;
2008-04-14 19:28:57 +00:00
hasPrototype := True;
2008-03-09 20:36:27 +00:00
end;
end;
2008-02-26 21:53:11 +00:00
var
2008-04-14 19:28:57 +00:00
itemProperty: TXMLDataBindingItemProperty;
propertyIndex: Integer;
propertyItem: TXMLDataBindingProperty;
2008-02-26 21:53:11 +00:00
begin
2008-04-14 19:28:57 +00:00
if not (ASection in [dxsClass, dxsImplementation]) then
2008-03-09 20:36:27 +00:00
Exit;
2008-02-26 21:53:11 +00:00
2008-04-14 19:28:57 +00:00
if (ASection = dxsClass) and
(not AItem.IsCollection) then
WriteInlineCollectionFields(AWriter, AItem);
2008-02-26 21:53:11 +00:00
2008-03-09 20:36:27 +00:00
2008-04-14 19:28:57 +00:00
hasPrototype := False;
2008-04-14 19:28:57 +00:00
for propertyIndex := 0 to Pred(AItem.PropertyCount) do
2008-02-20 06:52:00 +00:00
begin
2008-04-14 19:28:57 +00:00
propertyItem := AItem.Properties[propertyIndex];
if (not AItem.IsCollection) and Assigned(propertyItem.Collection) then
2008-03-09 20:36:27 +00:00
begin
WritePrototype;
2008-03-12 06:31:09 +00:00
{ Inline collection }
if ASection = dxsImplementation then
2008-04-14 19:28:57 +00:00
begin
if propertyItem.PropertyType = ptItem then
begin
if propertyItem.HasTargetNamespace then
AWriter.WriteLineNamedFmt(' RegisterChildNode(''%<ItemSourceName>:s'', %<ItemClass>:s, ''%<Namespace>:s'');',
['ItemSourceName', propertyItem.Name,
'ItemClass', GetDataTypeName(propertyItem, False),
'Namespace', propertyItem.TargetNamespace])
else
AWriter.WriteLineNamedFmt(' RegisterChildNode(''%<ItemSourceName>:s'', %<ItemClass>:s);',
['ItemSourceName', propertyItem.Name,
'ItemClass', GetDataTypeName(propertyItem, False)]);
end;
AWriter.WriteLineNamedFmt(' %<FieldName>:s := CreateCollection(%<CollectionClass>:s, %<ItemInterface>:s, ''%<ItemSourceName>:s'') as %<CollectionInterface>:s;',
['FieldName', PrefixField + propertyItem.TranslatedName,
'CollectionClass', PrefixClass + propertyItem.Collection.TranslatedName,
'CollectionInterface', PrefixInterface + propertyItem.Collection.TranslatedName,
'ItemInterface', GetDataTypeName(propertyItem, True),
'ItemSourceName', propertyItem.Name]);
end;
end;
if propertyItem.PropertyType = ptItem then
begin
itemProperty := TXMLDataBindingItemProperty(propertyItem);
if (not AItem.IsCollection) or
(propertyItem <> AItem.CollectionItem) then
2008-03-09 20:36:27 +00:00
begin
{ Item property }
if Assigned(itemProperty.Item) and
(itemProperty.Item.ItemType = itInterface) then
begin
case ASection of
dxsClass:
2008-04-14 19:28:57 +00:00
WritePrototype;
dxsImplementation:
begin
WritePrototype;
if propertyItem.HasTargetNamespace then
AWriter.WriteLineNamedFmt(' RegisterChildNode(''%<SourceName>:s'', TXML%<Name>:s, ''%<Namespace>:s'');',
['SourceName', propertyItem.Name,
'Name', itemProperty.Item.TranslatedName,
'Namespace', propertyItem.TargetNamespace])
else
AWriter.WriteLineNamedFmt(' RegisterChildNode(''%<SourceName>:s'', TXML%<Name>:s);',
['SourceName', propertyItem.Name,
'Name', itemProperty.Item.TranslatedName]);
end;
end;
2008-04-14 19:28:57 +00:00
end;
end;
end;
end;
2008-03-09 20:36:27 +00:00
2008-04-14 19:28:57 +00:00
if AItem.IsCollection then
begin
WritePrototype;
2008-03-09 20:36:27 +00:00
2008-04-14 19:28:57 +00:00
if ASection = dxsImplementation then
begin
WritePrototype;
if AItem.CollectionItem.HasTargetNamespace then
AWriter.WriteLineNamedFmt(' RegisterChildNode(''%<SourceName>:s'', %<DataClass>:s, ''%<Namespace>:s'');',
['SourceName', AItem.CollectionItem.Name,
'DataClass', GetDataTypeName(AItem.CollectionItem, False),
'Namespace', AItem.CollectionItem.TargetNamespace])
else
AWriter.WriteLineNamedFmt(' RegisterChildNode(''%<SourceName>:s'', %<DataClass>:s);',
['SourceName', AItem.CollectionItem.Name,
'DataClass', GetDataTypeName(AItem.CollectionItem, False)]);
AWriter.WriteLine;
AWriter.WriteLine(' ItemTag := ''%s'';', [AItem.CollectionItem.Name]);
AWriter.WriteLine(' ItemInterface := %s;', [GetDataTypeName(AItem.CollectionItem, True)]);
AWriter.WriteLine;
2008-04-14 19:28:57 +00:00
end;
end;
2008-04-14 19:28:57 +00:00
if hasPrototype and (ASection = dxsImplementation) then
begin
AWriter.WriteLine(' inherited;');
if AItem.IsCollection and (AItem.TargetNamespace <> AItem.CollectionItem.TargetNamespace) then
begin
AWriter.WriteLine;
AWriter.WriteLine(' ItemNS := ''%s'';', [AItem.CollectionItem.TargetNamespace]);
end;
AWriter.WriteLine('end;');
AWriter.WriteLine;
2008-04-14 19:28:57 +00:00
end;
end;
2008-03-09 20:36:27 +00:00
function TDelphiXMLDataBindingGenerator.WriteInlineCollectionFields(AWriter: TNamedFormatWriter; AItem: TXMLDataBindingInterface): Boolean;
2008-04-14 19:28:57 +00:00
var
propertyIndex: Integer;
collectionProperty: TXMLDataBindingProperty;
2008-03-17 12:17:55 +00:00
2008-04-14 19:28:57 +00:00
begin
Result := False;
2008-03-17 12:17:55 +00:00
2008-04-14 19:28:57 +00:00
for propertyIndex := 0 to Pred(AItem.PropertyCount) do
if AItem.Properties[propertyIndex].IsRepeating then
begin
collectionProperty := AItem.Properties[propertyIndex];
2008-03-17 12:17:55 +00:00
2008-04-14 19:28:57 +00:00
if Assigned(collectionProperty.Collection) then
begin
if not Result then
begin
AWriter.WriteLine(' private');
2008-04-14 19:28:57 +00:00
Result := True;
2008-03-09 20:36:27 +00:00
end;
2008-04-14 19:28:57 +00:00
AWriter.WriteLineNamedFmt(' %<PropertyName>:s: %<DataInterface>:s;',
['PropertyName', PrefixField + collectionProperty.TranslatedName,
'DataInterface', PrefixInterface + collectionProperty.Collection.TranslatedName]);
2008-03-09 20:36:27 +00:00
end;
end;
end;
procedure TDelphiXMLDataBindingGenerator.WriteSchemaInterfaceProperties(AWriter: TNamedFormatWriter; AItem: TXMLDataBindingInterface; ASection: TDelphiXMLSection);
2008-04-14 19:28:57 +00:00
var
propertyIndex: Integer;
itemProperty: TXMLDataBindingProperty;
hasMembers: Boolean;
firstMember: Boolean;
member: TDelphiXMLMember;
2008-03-09 20:36:27 +00:00
begin
TX2GlobalLog.Verbose('WriteSchemaInterfaceProperties: ' + AItem.Name);
2008-04-14 19:28:57 +00:00
if ASection = dxsForward then
2008-03-17 12:17:55 +00:00
Exit;
2008-04-14 19:28:57 +00:00
if ASection in [dxsClass, dxsImplementation] then
WriteAfterConstruction(AWriter, AItem, ASection);
2008-03-09 20:36:27 +00:00
2008-04-14 19:28:57 +00:00
if ASection = dxsClass then
AWriter.WriteLine(' protected');
2008-03-09 20:36:27 +00:00
WriteValidate(AWriter, AItem, ASection);
WriteEnumeratorMethod(AWriter, AItem, ASection);
hasMembers := WriteSchemaInterfaceCollectionProperties(AWriter, AItem, ASection);
2008-03-09 20:36:27 +00:00
2008-04-14 19:28:57 +00:00
for member := Low(TDelphiXMLMember) to High(TDelphiXMLMember) do
begin
firstMember := True;
2008-03-09 20:36:27 +00:00
2008-04-14 19:28:57 +00:00
for propertyIndex := 0 to Pred(AItem.PropertyCount) do
begin
itemProperty := AItem.Properties[propertyIndex];
if WriteSchemaInterfaceProperty(AWriter, AItem, itemProperty, ASection, member,
2008-04-14 19:28:57 +00:00
hasMembers and firstMember and (ASection in [dxsInterface, dxsClass])) then
2008-03-09 20:36:27 +00:00
begin
2008-04-14 19:28:57 +00:00
firstMember := False;
hasMembers := True;
2008-03-09 20:36:27 +00:00
end;
2008-04-14 19:28:57 +00:00
end;
2008-02-26 21:53:11 +00:00
end;
2008-03-09 20:36:27 +00:00
end;
2008-02-26 21:53:11 +00:00
function TDelphiXMLDataBindingGenerator.WriteSchemaInterfaceCollectionProperties(AWriter: TNamedFormatWriter; AItem: TXMLDataBindingInterface; ASection: TDelphiXMLSection): Boolean;
var
2008-04-14 19:28:57 +00:00
dataIntfName: String;
dataTypeName: String;
dataClassName: String;
collectionItem: TXMLDataBindingItem;
2008-03-17 12:17:55 +00:00
sourceCode: TNamedFormatStringList;
typeDef: IXMLTypeDef;
typeMapping: TTypeMapping;
2008-03-09 20:36:27 +00:00
begin
2008-04-14 19:28:57 +00:00
Result := False;
if not AItem.IsCollection then
Exit;
2008-03-09 20:36:27 +00:00
case AItem.CollectionItem.PropertyType of
ptSimple:
begin
dataTypeName := TranslateDataType(TXMLDataBindingSimpleProperty(AItem.CollectionItem).DataType);
dataClassName := ItemClass;
dataIntfName := ItemInterface;
end;
ptItem:
begin
2008-04-14 19:28:57 +00:00
collectionItem := TXMLDataBindingItemProperty(AItem.CollectionItem).Item;
if collectionItem.ItemType = itEnumeration then
begin
// #ToDo1 (MvR) 17-3-2008: DataType and conversions for enumerations
dataTypeName := PrefixInterface + collectionItem.TranslatedName;
dataClassName := PrefixClass + collectionItem.TranslatedName;
dataIntfName := dataTypeName;
end else
begin
dataTypeName := PrefixInterface + collectionItem.TranslatedName;
dataClassName := PrefixClass + collectionItem.TranslatedName;
dataIntfName := dataTypeName;
end;
end;
end;
2008-03-09 20:36:27 +00:00
sourceCode := TNamedFormatStringList.Create;
2008-03-17 12:17:55 +00:00
try
case ASection of
dxsInterface,
dxsClass:
begin
sourceCode.Add(' function Get_%<ItemName>:s(Index: Integer): %<DataType>:s;');
case AItem.CollectionItem.PropertyType of
ptSimple:
begin
sourceCode.Add(' function Add(%<ItemName>:s: %<DataType>:s): %<DataInterface>:s;');
sourceCode.Add(' function Insert(Index: Integer; %<ItemName>:s: %<DataType>:s): %<DataInterface>:s;');
end;
ptItem:
begin
sourceCode.Add(' function Add: %<DataType>:s;');
sourceCode.Add(' function Insert(Index: Integer): %<DataType>:s;');
end;
end;
2008-03-17 12:17:55 +00:00
end;
2008-04-14 19:28:57 +00:00
2008-03-17 12:17:55 +00:00
dxsImplementation:
begin
case AItem.CollectionItem.PropertyType of
ptSimple:
begin
typeDef := TXMLDataBindingSimpleProperty(AItem.CollectionItem).DataType;
sourceCode.Add('function TXML%<Name>:s.Get_%<ItemName>:s(Index: Integer): %<DataType>:s;');
if GetDataTypeMapping(typeDef, typeMapping) and (typeMapping.Conversion = tcString) then
sourceCode.Add(XMLToNativeDataType('Result', 'List[Index].Text', typeDef, dntCustom, AItem.CollectionItem.TargetNamespace))
else
sourceCode.Add(XMLToNativeDataType('Result', 'List[Index].NodeValue', typeDef, dntCustom, AItem.CollectionItem.TargetNamespace));
sourceCode.AddLn;
sourceCode.Add('function TXML%<Name>:s.Add(%<ItemName>:s: %<DataType>:s): %<DataInterface>:s;');
sourceCode.Add(NativeDataTypeToXML('Result.NodeValue', '%<ItemName>:s', typeDef, dntCustom, '',
' Result := AddItem(-1);'));
sourceCode.AddLn;
sourceCode.Add('function TXML%<Name>:s.Insert(Index: Integer; %<ItemName>:s: %<DataType>:s): %<DataInterface>:s;');
sourceCode.Add(NativeDataTypeToXML('Result.NodeValue', '%<ItemName>:s', typeDef, dntCustom, '',
' Result := AddItem(Index);'));
sourceCode.AddLn;
end;
2008-03-17 12:17:55 +00:00
ptItem:
begin
sourceCode.Add('function TXML%<Name>:s.Get_%<ItemName>:s(Index: Integer): %<DataType>:s;');
sourceCode.Add('begin');
sourceCode.Add(' Result := (List[Index] as %<DataType>:s);');
sourceCode.Add('end;');
sourceCode.AddLn;
sourceCode.Add('function TXML%<Name>:s.Add: %<DataType>:s;');
sourceCode.Add('begin');
sourceCode.Add(' Result := (AddItem(-1) as %<DataType>:s);');
sourceCode.Add('end;');
sourceCode.AddLn;
sourceCode.Add('function TXML%<Name>:s.Insert(Index: Integer): %<DataType>:s;');
sourceCode.Add('begin');
sourceCode.Add(' Result := (AddItem(Index) as %<DataType>:s);');
sourceCode.Add('end;');
sourceCode.AddLn;
end;
end;
2008-03-17 12:17:55 +00:00
end;
end;
2008-03-09 20:36:27 +00:00
2008-04-14 19:28:57 +00:00
if ASection = dxsInterface then
begin
sourceCode.AddLn;
sourceCode.Add(' property %<ItemName>:s[Index: Integer]: %<DataType>:s read Get_%<ItemName>:s; default;');
end;
Result := (sourceCode.Count > 0);
if Result then
AWriter.Write(sourceCode.Format(['Name', AItem.TranslatedName,
2008-04-14 19:28:57 +00:00
'ItemName', AItem.CollectionItem.TranslatedName,
'ItemSourceName', AItem.CollectionItem.Name,
'DataType', dataTypeName,
'DataClass', dataClassName,
'DataInterface', dataIntfName]));
finally
FreeAndNil(sourceCode);
end;
end;
function TDelphiXMLDataBindingGenerator.WriteSchemaInterfaceProperty(AWriter: TNamedFormatWriter; AItem: TXMLDataBindingInterface; AProperty: TXMLDataBindingProperty; ASection: TDelphiXMLSection; AMember: TDelphiXMLMember; ANewLine: Boolean): Boolean;
2008-04-14 19:28:57 +00:00
procedure WriteNewLine;
begin
if ANewLine then
AWriter.WriteLine;
2008-04-14 19:28:57 +00:00
end;
function IsReadOnly(AProperty: TXMLDataBindingProperty): Boolean;
var
typeMapping: TTypeMapping;
begin
if Assigned(AProperty.Collection) then
exit(True);
Result := AProperty.IsReadOnly;
if (not Result) and (AProperty.PropertyType = ptSimple) then
begin
if GetDataTypeMapping(TXMLDataBindingSimpleProperty(AProperty).DataType, typeMapping) then
Result := (typeMapping.Conversion = tcNode);
end;
end;
2008-04-14 19:28:57 +00:00
var
sourceCode: TNamedFormatStringList;
writeOptional: Boolean;
2008-04-21 15:24:33 +00:00
writeNil: Boolean;
2008-04-14 19:28:57 +00:00
writeTextProp: Boolean;
propertyItem: TXMLDataBindingItem;
dataTypeName: String;
value: String;
propertyItemName: String;
fieldName: String;
writeStream: Boolean;
typeMapping: TTypeMapping;
nodeType: TDelphiNodeType;
2008-04-14 19:28:57 +00:00
begin
Result := False;
if AProperty = AItem.CollectionItem then
Exit;
2008-04-21 15:24:33 +00:00
2008-04-14 19:28:57 +00:00
{ If the property has a collection, it's Count property will be enough
to check if an item is present, no need to write a HasX method. }
2008-04-21 15:24:33 +00:00
writeOptional := False;
writeNil := AProperty.IsNillable;
2008-04-21 15:24:33 +00:00
if AMember in [dxmPropertyGet, dxmPropertyDeclaration] then
writeOptional := not Assigned(AProperty.Collection) and
AProperty.IsOptional;
2008-04-14 19:28:57 +00:00
writeStream := False;
if (AMember = dxmPropertyMethods) and (AProperty.PropertyType = ptSimple) then
begin
if GetDataTypeMapping(TXMLDataBindingSimpleProperty(AProperty).DataType, typeMapping) then
writeStream := (typeMapping.Conversion = tcBase64);
end;
2008-04-14 19:28:57 +00:00
dataTypeName := '';
propertyItem := nil;
fieldName := '';
{ Get data type }
writeTextProp := False;
if Assigned(AProperty.Collection) then
begin
dataTypeName := PrefixInterface + AProperty.Collection.TranslatedName;
fieldName := PrefixField + AProperty.TranslatedName;
end else
begin
case AProperty.PropertyType of
ptSimple:
dataTypeName := TranslateDataType(TXMLDataBindingSimpleProperty(AProperty).DataType);
ptItem:
2008-03-17 12:17:55 +00:00
begin
2008-04-14 19:28:57 +00:00
propertyItem := TXMLDataBindingItemProperty(AProperty).Item;
if Assigned(propertyItem) then
begin
if propertyItem.ItemType = itEnumeration then
begin
dataTypeName := PrefixClass;
writeTextProp := True;
end else
dataTypeName := PrefixInterface;
dataTypeName := dataTypeName + propertyItem.TranslatedName;
end;
2008-03-17 12:17:55 +00:00
end;
2008-04-14 19:28:57 +00:00
end;
end;
2008-03-09 20:36:27 +00:00
2008-04-14 19:28:57 +00:00
if Length(dataTypeName) = 0 then
Exit;
sourceCode := TNamedFormatStringList.Create;
2008-04-14 19:28:57 +00:00
try
case ASection of
dxsInterface,
2008-03-17 12:17:55 +00:00
dxsClass:
begin
2008-04-14 19:28:57 +00:00
{ Interface declaration }
case AMember of
dxmPropertyGet:
begin
WriteNewLine;
if writeOptional then
begin
2008-04-14 19:28:57 +00:00
sourceCode.Add(PropertyIntfMethodGetOptional);
if AProperty.PropertyType = ptSimple then
sourceCode.Add(PropertyIntfMethodGetOptionalOrDefault);
end;
2008-04-14 19:28:57 +00:00
2008-04-21 15:24:33 +00:00
if writeNil then
sourceCode.Add(PropertyIntfMethodGetNil);
2008-04-14 19:28:57 +00:00
if writeTextProp then
sourceCode.Add(PropertyIntfMethodGetText);
sourceCode.Add(PropertyIntfMethodGet);
end;
dxmPropertySet:
if not IsReadOnly(AProperty) then
2008-04-14 19:28:57 +00:00
begin
WriteNewLine;
if writeNil then
sourceCode.Add(PropertyIntfMethodSetNil);
2008-04-14 19:28:57 +00:00
if writeTextProp then
sourceCode.Add(PropertyIntfMethodSetText);
sourceCode.Add(PropertyIntfMethodSet);
end;
dxmPropertyMethods:
if writeStream then
begin
sourceCode.Add(PropertyIntfMethodLoadFromStream);
sourceCode.Add(PropertyIntfMethodLoadFromFile);
sourceCode.Add(PropertyIntfMethodSaveToStream);
sourceCode.Add(PropertyIntfMethodSaveToFile);
end;
2008-04-14 19:28:57 +00:00
dxmPropertyDeclaration:
if ASection = dxsInterface then
begin
WriteNewLine;
if writeOptional then
sourceCode.Add(PropertyInterfaceOptional);
if IsReadOnly(AProperty) then
2008-04-14 19:28:57 +00:00
begin
if writeNil then
sourceCode.Add(PropertyInterfaceNilReadOnly);
2008-04-14 19:28:57 +00:00
if writeTextProp then
sourceCode.Add(PropertyInterfaceTextReadOnly);
sourceCode.Add(PropertyInterfaceReadOnly);
end else
begin
if writeNil then
sourceCode.Add(PropertyInterfaceNil);
2008-04-14 19:28:57 +00:00
if writeTextProp then
sourceCode.Add(PropertyInterfaceText);
sourceCode.Add(PropertyInterface);
end;
end;
end;
end;
dxsImplementation:
begin
{ Implementation }
case AMember of
dxmPropertyGet:
begin
nodeType := GetDelphiNodeType(AProperty);
2008-04-14 19:28:57 +00:00
WriteNewLine;
2008-04-21 15:24:33 +00:00
2008-04-14 19:28:57 +00:00
if writeOptional then
2017-07-21 07:47:14 +00:00
begin
if HasChecksEmpty and (AProperty.PropertyType = ptSimple) and (not Assigned(AProperty.Collection)) then
begin
if AProperty.IsAttribute then
sourceCode.Add(PropertyImplMethodGetOptionalAttrEmpty)
else
sourceCode.Add(PropertyImplMethodGetOptionalEmpty[GetDelphiElementType(nodeType)]);
end else
begin
2017-07-21 07:47:14 +00:00
if AProperty.IsAttribute then
sourceCode.Add(PropertyImplMethodGetOptionalAttr)
else
sourceCode.Add(PropertyImplMethodGetOptional[GetDelphiElementType(nodeType)]);
end;
if AProperty.PropertyType = ptSimple then
sourceCode.Add(PropertyImplMethodGetOptionalOrDefault);
2017-07-21 07:47:14 +00:00
end;
2008-04-14 19:28:57 +00:00
2008-04-21 15:24:33 +00:00
if writeNil then
sourceCode.Add(PropertyImplMethodGetNil[GetDelphiElementType(nodeType)]);
2008-04-21 15:24:33 +00:00
2008-04-14 19:28:57 +00:00
if writeTextProp then
if AProperty.IsAttribute then
sourceCode.Add(PropertyImplMethodGetTextAttr)
else
sourceCode.Add(PropertyImplMethodGetText[GetDelphiElementType(nodeType)]);
2008-04-14 19:28:57 +00:00
sourceCode.Add('function TXML%<Name>:s.Get%<PropertyName>:s: %<DataType>:s;');
case AProperty.PropertyType of
ptSimple:
if Assigned(AProperty.Collection) then
begin
sourceCode.Add('begin');
sourceCode.Add(' Result := %<FieldName>:s;');
sourceCode.Add('end;');
end else
sourceCode.Add(XMLToNativeDataType('Result',
'%<PropertySourceName>:s',
TXMLDataBindingSimpleProperty(AProperty).DataType,
nodeType,
AProperty.TargetNamespace));
2008-04-14 19:28:57 +00:00
ptItem:
begin
if Assigned(AProperty.Collection) then
begin
sourceCode.Add('begin');
sourceCode.Add(' Result := %<FieldName>:s;');
sourceCode.Add('end;');
end else
begin
if Assigned(propertyItem) then
begin
case propertyItem.ItemType of
itInterface:
begin
sourceCode.Add('begin');
if AProperty.HasTargetNamespace then
2013-06-21 10:25:49 +00:00
sourceCode.Add(' Result := (ChildNodesNS[''%<PropertySourceName>:s'', ''%<Namespace>:s''] as IXML%<PropertyItemName>:s);')
else
sourceCode.Add(' Result := (ChildNodes[''%<PropertySourceName>:s''] as IXML%<PropertyItemName>:s);');
2008-04-14 19:28:57 +00:00
sourceCode.Add('end;');
end;
itEnumeration:
begin
sourceCode.Add('begin');
sourceCode.Add(' Result := StringTo%<PropertyItemName>:s(Get%<PropertyName>:sText);');
sourceCode.Add('end;');
end;
end;
end;
end;
end;
end;
sourceCode.AddLn;
end;
2008-04-14 19:28:57 +00:00
dxmPropertySet:
if not IsReadOnly(AProperty) then
2008-04-14 19:28:57 +00:00
begin
nodeType := GetDelphiNodeType(AProperty);
2008-04-14 19:28:57 +00:00
WriteNewLine;
if writeNil then
sourceCode.Add(PropertyImplMethodSetNil[GetDelphiElementType(nodeType)]);
2008-04-14 19:28:57 +00:00
if writeTextProp then
if AProperty.IsAttribute then
sourceCode.Add(PropertyImplMethodSetTextAttr)
else
sourceCode.Add(PropertyImplMethodSetText[GetDelphiElementType(nodeType)]);
2008-04-14 19:28:57 +00:00
sourceCode.Add('procedure TXML%<Name>:s.Set%<PropertyName>:s(const Value: %<DataType>:s);');
value := '%<PropertySourceName>:s';
if Assigned(propertyItem) and (propertyItem.ItemType = itEnumeration) then
begin
sourceCode.Add(NativeDataTypeToXML(value, '%<PropertyItemName>:sValues[Value]', nil,
nodeType,
AProperty.TargetNamespace));
2008-04-14 19:28:57 +00:00
end else
begin
if AProperty.PropertyType <> ptSimple then
raise Exception.Create('Setter must be a simple type');
sourceCode.Add(NativeDataTypeToXML(value, 'Value',
TXMLDataBindingSimpleProperty(AProperty).DataType,
nodeType,
AProperty.TargetNamespace));
2008-04-14 19:28:57 +00:00
end;
sourceCode.AddLn;
end;
dxmPropertyMethods:
if writeStream then
begin
nodeType := GetDelphiElementType(GetDelphiNodeType(AProperty));
sourceCode.Add(PropertyImplMethodLoadFromStream[nodeType]);
sourceCode.Add(PropertyImplMethodLoadFromFile[nodeType]);
sourceCode.Add(PropertyImplMethodSaveToStream[nodeType]);
sourceCode.Add(PropertyImplMethodSaveToFile[nodeType]);
end;
2008-04-14 19:28:57 +00:00
end;
2008-03-17 12:17:55 +00:00
end;
end;
2008-03-09 20:36:27 +00:00
2008-04-14 19:28:57 +00:00
propertyItemName := '';
if Assigned(propertyItem) then
propertyItemName := propertyItem.TranslatedName;
Result := (sourceCode.Count > 0);
if Result then
AWriter.Write(sourceCode.Format(['Name', AItem.TranslatedName,
2008-04-14 19:28:57 +00:00
'PropertySourceName', AProperty.Name,
'PropertyName', AProperty.TranslatedName,
'PropertyItemName', propertyItemName,
'DataType', dataTypeName,
'FieldName', fieldName,
'Namespace', AProperty.TargetNamespace]));
2008-03-17 12:17:55 +00:00
finally
FreeAndNil(sourceCode);
2008-03-09 20:36:27 +00:00
end;
2008-02-26 21:53:11 +00:00
end;
procedure TDelphiXMLDataBindingGenerator.WriteSchemaEnumeration(AWriter: TNamedFormatWriter; AItem: TXMLDataBindingEnumeration; ASection: TDelphiXMLSection);
2008-02-26 21:53:11 +00:00
var
2008-03-09 20:36:27 +00:00
memberIndex: Integer;
2008-02-26 21:53:11 +00:00
enumStart: String;
lineIndent: String;
begin
2008-03-09 20:36:27 +00:00
if (ASection <> dxsForward) or (AItem.MemberCount = 0) then
2008-02-26 21:53:11 +00:00
exit;
enumStart := NamedFormat(' TXML%<Name>:s = (',
['Name', AItem.TranslatedName]);
AWriter.Write(enumStart);
2008-02-26 21:53:11 +00:00
lineIndent := StringOfChar(' ', Length(enumStart));
2008-03-09 20:36:27 +00:00
for memberIndex := 0 to Pred(AItem.MemberCount) do
2008-02-26 21:53:11 +00:00
begin
2008-03-09 20:36:27 +00:00
if memberIndex > 0 then
AWriter.Write(lineIndent);
2008-02-26 21:53:11 +00:00
AWriter.Write(AItem.Members[memberIndex].TranslatedName);
2008-02-26 21:53:11 +00:00
2008-03-09 20:36:27 +00:00
if memberIndex < Pred(AItem.MemberCount) then
AWriter.WriteLine(',')
2008-02-26 21:53:11 +00:00
else
AWriter.WriteLine(');');
2008-02-26 21:53:11 +00:00
end;
end;
procedure TDelphiXMLDataBindingGenerator.WriteSchemaEnumerationArray(AWriter: TNamedFormatWriter; AItem: TXMLDataBindingEnumeration);
2008-02-26 21:53:11 +00:00
var
2008-03-09 20:36:27 +00:00
memberIndex: Integer;
enumStart: String;
lineIndent: String;
2008-02-26 21:53:11 +00:00
begin
2008-03-09 20:36:27 +00:00
if (AItem.MemberCount = 0) then
exit;
2008-02-26 21:53:11 +00:00
enumStart := NamedFormat(' %<Name>:sValues: ', ['Name', AItem.TranslatedName]);
AWriter.WriteLine(enumStart + NamedFormat('array[TXML%<Name>:s] of WideString =',
['Name', AItem.TranslatedName]));
2008-03-09 20:36:27 +00:00
lineIndent := StringOfChar(' ', Length(enumStart));
2008-02-26 21:53:11 +00:00
AWriter.WriteLine(lineIndent + '(');
2008-02-26 21:53:11 +00:00
2008-03-09 20:36:27 +00:00
for memberIndex := 0 to Pred(AItem.MemberCount) do
2008-02-26 21:53:11 +00:00
begin
AWriter.Write(NamedFormat('%<Indent>:s ''%<Name>:s''',
['Indent', lineIndent,
'Name', AItem.Members[memberIndex].Name]));
2008-02-26 21:53:11 +00:00
2008-03-09 20:36:27 +00:00
if memberIndex < Pred(AItem.MemberCount) then
AWriter.WriteLine(',')
2008-03-09 20:36:27 +00:00
else
AWriter.WriteLine;
2008-02-20 06:52:00 +00:00
end;
AWriter.WriteLine(lineIndent + ');');
AWriter.WriteLine;
2008-02-20 06:52:00 +00:00
end;
procedure TDelphiXMLDataBindingGenerator.WriteValidate(AWriter: TNamedFormatWriter; AItem: TXMLDataBindingInterface; ASection: TDelphiXMLSection);
begin
if AItem.DocumentElement then
begin
case ASection of
dxsInterface,
dxsClass:
AWriter.WriteLine(XSDValidateDocumentMethodInterface);
dxsImplementation:
AWriter.WriteLineNamedFmt(XSDValidateDocumentMethodImplementation,
['Name', AItem.TranslatedName]);
end;
end;
if AItem.CanValidate then
begin
case ASection of
dxsInterface,
dxsClass:
begin
AWriter.WriteLine(XSDValidateMethodInterface);
AWriter.WriteLine('');
end;
dxsImplementation:
begin
WriteValidateImplementation(AWriter, AItem, False);
WriteValidateImplementation(AWriter, AItem, True);
end;
end;
end;
end;
procedure TDelphiXMLDataBindingGenerator.WriteValidateImplementation(AWriter: TNamedFormatWriter; AItem: TXMLDataBindingInterface; AStrict: Boolean);
procedure AddArrayElement(var AOutput: string; var ACount: Integer; const AValue: string);
begin
AOutput := AOutput + ', ';
{ Prevent "Line too long" on large elements }
if (ACount > 0) and (ACount mod 5 = 0) then
AOutput := AOutput + XSDValidateMethodImplementationArrayBreak;
AOutput := AOutput + AValue;
Inc(ACount);
end;
var
propertyIndex: Integer;
propertyItem: TXMLDataBindingProperty;
elementSortCount: Integer;
elementSortOrder: string;
elementRequired: string;
elementRequiredCount: Integer;
attributeRequired: string;
attributeRequiredCount: Integer;
begin
AWriter.WriteLineNamedFmt(IfThen(AStrict, XSDValidateStrictMethodImplementationBegin, XSDValidateMethodImplementationBegin),
['Name', AItem.TranslatedName]);
elementSortCount := 0;
elementSortOrder := '';
elementRequiredCount := 0;
elementRequired := '';
attributeRequiredCount := 0;
attributeRequired := '';
for propertyIndex := 0 to Pred(AItem.PropertyCount) do
begin
propertyItem := AItem.Properties[propertyIndex];
if propertyItem.IsAttribute then
begin
if not propertyItem.IsOptional then
AddArrayElement(attributeRequired, attributeRequiredCount, QuotedStr(propertyItem.Name));
end else if not propertyItem.IsNodeValue then
begin
AddArrayElement(elementSortOrder, elementSortCount, QuotedStr(propertyItem.Name));
if (not propertyItem.IsOptional) and (not propertyItem.IsRepeating) then
begin
case propertyItem.PropertyType of
ptSimple:
AddArrayElement(elementRequired, elementRequiredCount, QuotedStr(propertyItem.Name));
ptItem:
{ For Item properties, we call our getter property. This ensures the child element exists,
but also that it is created using our binding implementation. Otherwise there will be no
IXSDValidate interface to call on the newly created node. }
AWriter.WriteLineNamedFmt(XSDValidateMethodImplementationComplex,
['Name', propertyItem.TranslatedName]);
end;
end;
end;
end;
if elementRequiredCount > 0 then
begin
Delete(elementRequired, 1, 2);
AWriter.WriteLineNamedFmt(IfThen(AStrict, XSDValidateStrictMethodImplementationRequired, XSDValidateMethodImplementationRequired),
['RequiredElements', elementRequired]);
end;
if attributeRequiredCount > 0 then
begin
Delete(attributeRequired, 1, 2);
AWriter.WriteLineNamedFmt(IfThen(AStrict, XSDValidateStrictMethodImplementationAttrib, XSDValidateMethodImplementationAttrib),
['RequiredAttributes', attributeRequired]);
end;
if elementSortCount > 1 then
begin
Delete(elementSortOrder, 1, 2);
AWriter.WriteLineNamedFmt(XSDValidateMethodImplementationSort,
['SortOrder', elementSortOrder]);
end;
AWriter.WriteLine(IfThen(AStrict, XSDValidateStrictMethodImplementationEnd, XSDValidateMethodImplementationEnd));
end;
procedure TDelphiXMLDataBindingGenerator.WriteEnumeratorMethod(AWriter: TNamedFormatWriter; AItem: TXMLDataBindingInterface; ASection: TDelphiXMLSection);
begin
if not AItem.IsCollection then
Exit;
case ASection of
dxsInterface,
dxsClass:
begin
AWriter.WriteLineNamedFmt(EnumeratorMethodInterface,
['Name', AItem.TranslatedName]);
AWriter.WriteLine('');
end;
dxsImplementation:
begin
AWriter.WriteLineNamedFmt(EnumeratorMethodImplementation,
['Name', AItem.TranslatedName]);
end;
end;
end;
procedure TDelphiXMLDataBindingGenerator.WriteEnumerator(AWriter: TNamedFormatWriter; AItem: TXMLDataBindingInterface; ASection: TDelphiXMLSection);
begin
if not AItem.IsCollection then
Exit;
2013-07-03 14:53:48 +00:00
case ASection of
dxsInterface:
begin
AWriter.WriteLineNamedFmt(EnumeratorInterface,
['Name', AItem.TranslatedName,
'DataType', GetDataTypeName(AItem.CollectionItem, True),
'GUID', CreateNewGUID]);
AWriter.WriteLine('');
end;
dxsClass:
begin
AWriter.WriteLineNamedFmt(EnumeratorClass,
['Name', AItem.TranslatedName,
'DataType', GetDataTypeName(AItem.CollectionItem, True)]);
AWriter.WriteLine('');
end;
dxsImplementation:
begin
AWriter.WriteLineNamedFmt(EnumeratorImplementation,
['Name', AItem.TranslatedName,
'DataType', GetDataTypeName(AItem.CollectionItem, True)]);
end;
end;
end;
2008-04-14 19:28:57 +00:00
function TDelphiXMLDataBindingGenerator.GetDelphiNodeType(AProperty: TXMLDataBindingProperty): TDelphiNodeType;
begin
if AProperty.IsAttribute then
Result := dntAttribute
else if AProperty.IsNodeValue then
Result := dntNodeValue
else if AProperty.HasTargetNamespace then
Result := dntElementNS
2008-04-14 19:28:57 +00:00
else
Result := dntElement;
end;
function TDelphiXMLDataBindingGenerator.GetDelphiElementType(ANodeType: TDelphiNodeType): TDelphiElementType;
begin
if ANodeType = dntElementNS then
Result := dntElementNS
else
Result := dntElement;
end;
function TDelphiXMLDataBindingGenerator.DataTypeConversion(const ADestination, ASource: String; ADataType: IXMLTypeDef;
AAccessor: TDelphiAccessor; ANodeType: TDelphiNodeType;
const ATargetNamespace: string; const ALinesBefore: String = ''): String;
var
typeMapping: TTypeMapping;
2008-04-14 19:28:57 +00:00
conversion: String;
begin
with TNamedFormatStringList.Create do
try
2008-04-14 19:28:57 +00:00
if not (Assigned(ADataType) and GetDataTypeMapping(ADataType, typeMapping)) then
typeMapping.Conversion := tcNone;
Add('begin');
if Length(ALinesBefore) > 0 then
Add(ALinesBefore);
2008-04-14 19:28:57 +00:00
conversion := TypeConversion[AAccessor, ANodeType, typeMapping.Conversion];
if Length(conversion) = 0 then
conversion := TypeConversionNone[AAccessor, ANodeType];
Add(conversion);
Add('end;');
2008-04-14 19:28:57 +00:00
// #ToDo1 -oMvR: 6-4-2012: Namespace
2008-04-14 19:28:57 +00:00
Result := Trim(Format(['Destination', ADestination,
'Source', ASource,
'Namespace', ATargetNamespace]));
finally
Free;
end;
end;
function TDelphiXMLDataBindingGenerator.XMLToNativeDataType(const ADestination, ASource: String; ADataType: IXMLTypeDef;
ANodeType: TDelphiNodeType; const ATargetNamespace: string;
const ALinesBefore: String): String;
begin
Result := DataTypeConversion(ADestination, ASource, ADataType, daGet, ANodeType, ATargetNamespace, ALinesBefore);
end;
function TDelphiXMLDataBindingGenerator.NativeDataTypeToXML(const ADestination, ASource: String; ADataType: IXMLTypeDef;
ANodeType: TDelphiNodeType; const ATargetNamespace: string;
const ALinesBefore: String): String;
begin
Result := DataTypeConversion(ADestination, ASource, ADataType, daSet, ANodeType, ATargetNamespace, ALinesBefore);
end;
function TDelphiXMLDataBindingGenerator.CreateNewGUID: String;
2008-02-26 21:53:11 +00:00
var
guid: TGUID;
begin
Result := '{ GUID generation failed }';
if CreateGUID(guid) = S_OK then
Result := '[''' + GUIDToString(guid) + ''']';
end;
2008-02-20 06:52:00 +00:00
function TDelphiXMLDataBindingGenerator.DoGetFileName(const ASchemaName: String): String;
2008-04-14 19:20:55 +00:00
var
path: String;
fileName: String;
2008-02-20 06:52:00 +00:00
begin
Result := OutputPath;
if OutputType = otMultiple then
begin
2008-04-14 19:20:55 +00:00
path := IncludeTrailingPathDelimiter(Result);
fileName := ASchemaName + '.pas';
2008-02-20 06:52:00 +00:00
if Assigned(FOnGetFileName) then
2008-04-14 19:20:55 +00:00
FOnGetFileName(Self, ASchemaName, path, fileName);
Result := IncludeTrailingPathDelimiter(path) + fileName;
2008-02-20 06:52:00 +00:00
end;
end;
end.
2008-03-09 20:36:27 +00:00