Added support for strict(er) validation

Fixed setter being generated for repeating simple types (and in some cases, causing syntax errors)
This commit is contained in:
Mark van Renswoude 2017-07-19 13:58:31 +02:00
parent 79d87acb61
commit c16eb103da
3 changed files with 126 additions and 104 deletions

1
.gitignore vendored
View File

@ -3,3 +3,4 @@ Units/__history/
*.identcache
bin/
lib/
__history/

View File

@ -57,6 +57,7 @@ type
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);
@ -75,6 +76,7 @@ type
implementation
uses
StrUtils,
SysUtils,
X2UtNamedFormat,
@ -1113,6 +1115,9 @@ function TDelphiXMLDataBindingGenerator.WriteSchemaInterfaceProperty(AWriter: TN
typeMapping: TTypeMapping;
begin
if Assigned(AProperty.Collection) then
exit(True);
Result := AProperty.IsReadOnly;
if (not Result) and (AProperty.PropertyType = ptSimple) then
@ -1493,16 +1498,6 @@ end;
procedure TDelphiXMLDataBindingGenerator.WriteValidate(AWriter: TNamedFormatWriter; AItem: TXMLDataBindingInterface; ASection: TDelphiXMLSection);
var
propertyIndex: Integer;
propertyItem: TXMLDataBindingProperty;
elementSortOrder: string;
elementSortCount: Integer;
elementRequired: string;
elementRequiredCount: Integer;
attributeRequired: string;
attributeRequiredCount: Integer;
begin
if AItem.DocumentElement then
begin
@ -1529,91 +1524,106 @@ begin
dxsImplementation:
begin
AWriter.WriteLineNamedFmt(XSDValidateMethodImplementationBegin,
['Name', AItem.TranslatedName]);
elementSortOrder := '';
elementSortCount := 0;
elementRequired := '';
elementRequiredCount := 0;
attributeRequired := '';
attributeRequiredCount := 0;
for propertyIndex := 0 to Pred(AItem.PropertyCount) do
begin
propertyItem := AItem.Properties[propertyIndex];
if propertyItem.IsAttribute then
begin
if not propertyItem.IsOptional then
begin
attributeRequired := attributeRequired + ', ' + QuotedStr(propertyItem.Name);
Inc(attributeRequiredCount);
end;
end else if not propertyItem.IsNodeValue then
begin
elementSortOrder := elementSortOrder + ', ';
{ Prevent "Line too long" on large elements }
if (elementSortCount > 0) and (elementSortCount mod 5 = 0) then
elementSortOrder := elementSortOrder + XSDValidateMethodImplementationSortNewLine;
elementSortOrder := elementSortOrder + QuotedStr(propertyItem.Name);
Inc(elementSortCount);
if (not propertyItem.IsOptional) and (not propertyItem.IsRepeating) then
begin
case propertyItem.PropertyType of
ptSimple:
begin
elementRequired := elementRequired + ', ' + QuotedStr(propertyItem.Name);
Inc(elementRequiredCount);
end;
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(XSDValidateMethodImplementationRequired,
['RequiredElements', elementRequired]);
end;
if attributeRequiredCount > 0 then
begin
Delete(attributeRequired, 1, 2);
AWriter.WriteLineNamedFmt(XSDValidateMethodImplementationAttrib,
['RequiredAttributes', attributeRequired]);
end;
if elementSortCount > 1 then
begin
Delete(elementSortOrder, 1, 2);
AWriter.WriteLineNamedFmt(XSDValidateMethodImplementationSort,
['SortOrder', elementSortOrder]);
end;
AWriter.WriteLine(XSDValidateMethodImplementationEnd);
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

View File

@ -95,28 +95,39 @@ const
XSDValidateInterface = 'IXSDValidate';
XSDValidateInterface = 'IXSDValidate, IXSDValidateStrict';
XSDValidateDocumentMethodInterface = ' procedure XSDValidateDocument;';
XSDValidateDocumentMethodInterface = ' procedure XSDValidateDocument(AStrict: Boolean = False);';
XSDValidateDocumentMethodImplementation = 'procedure TXML%<Name>:s.XSDValidateDocument;' + CrLf +
'begin' + CrLf +
' XMLDataBindingUtils.XSDValidate(Self);' + CrLf +
'end;' + CrLf;
XSDValidateDocumentMethodImplementation = 'procedure TXML%<Name>:s.XSDValidateDocument(AStrict: Boolean);' + CrLf +
'begin' + CrLf +
' if AStrict then' + CrLf +
' XMLDataBindingUtils.XSDValidateStrict(Self)' + CrLf +
' else' + CrLf +
' XMLDataBindingUtils.XSDValidate(Self);' + CrLf +
'end;' + CrLf;
XSDValidateMethodInterface = ' procedure XSDValidate;';
XSDValidateMethodInterface = ' procedure XSDValidate;' + CrLf +
' procedure XSDValidateStrict(AResult: IXSDValidateStrictResult);';
XSDValidateMethodImplementationBegin = 'procedure TXML%<Name>:s.XSDValidate;' + CrLf +
'begin';
XSDValidateMethodImplementationBegin = 'procedure TXML%<Name>:s.XSDValidate;' + CrLf +
'begin';
XSDValidateMethodImplementationRequired = ' CreateRequiredElements(Self, [%<RequiredElements>:s]);';
XSDValidateMethodImplementationComplex = ' Get%<Name>:s;';
XSDValidateMethodImplementationAttrib = ' CreateRequiredAttributes(Self, [%<RequiredAttributes>:s]);';
XSDValidateMethodImplementationSort = ' SortChildNodes(Self, [%<SortOrder>:s]);';
XSDValidateMethodImplementationSortNewLine = #13#10 + ' ';
XSDValidateMethodImplementationRequired = ' CreateRequiredElements(Self, [%<RequiredElements>:s]);';
XSDValidateMethodImplementationComplex = ' Get%<Name>:s;';
XSDValidateMethodImplementationAttrib = ' CreateRequiredAttributes(Self, [%<RequiredAttributes>:s]);';
XSDValidateMethodImplementationSort = ' SortChildNodes(Self, [%<SortOrder>:s]);';
XSDValidateMethodImplementationArrayBreak = #13#10 + ' ';
XSDValidateMethodImplementationEnd = 'end;' + CrLf;
XSDValidateMethodImplementationEnd = 'end;' + CrLf;
XSDValidateStrictMethodImplementationBegin = 'procedure TXML%<Name>:s.XSDValidateStrict(AResult: IXSDValidateStrictResult);' + CrLf +
'begin';
XSDValidateStrictMethodImplementationRequired = ' ValidateRequiredElements(AResult, Self, [%<RequiredElements>:s]);';
XSDValidateStrictMethodImplementationAttrib = ' ValidateRequiredAttributes(AResult, Self, [%<RequiredAttributes>:s]);';
XSDValidateStrictMethodImplementationEnd = 'end;' + CrLf;
EnumeratorMethodInterface = ' function GetEnumerator: IXML%<Name>:sEnumerator;';