spiegel-keyman/developer/src/tike/compile/ValidateKeyboardInfo.pas

187 lines
4.6 KiB
ObjectPascal

unit ValidateKeyboardInfo;
interface
uses
System.JSON,
Keyman.Developer.System.Project.ProjectLog;
type
TValidateKeyboardInfo = class
private
FJsonFile: string;
FSilent: Boolean;
json: TJSONObject;
function DoFieldValidation: Boolean;
function LoadJsonFile: Boolean;
constructor Create(AJsonFile: string; ASilent: Boolean);
function Failed(message: string): Boolean;
procedure Warning(message: string);
procedure Info(message: string);
procedure Hint(message: string);
public
class function Execute(JsonFile, JsonSchemaPath: string; FDistribution, FSilent: Boolean; FCallback: TProjectLogObjectEvent): Boolean;
end;
implementation
uses
System.Classes,
System.Generics.Collections,
System.SysUtils,
Winapi.Windows,
BCP47Tag,
compile,
// Keyman.Developer.System.Project.ProjectLogConsole,
Keyman.System.CanonicalLanguageCodeUtils,
Keyman.System.KeyboardInfoFile,
Keyman.System.KMXFileLanguages;
{ TValidateKeyboardInfo }
const
SKeyboardInfoSourceSchemaJson = 'keyboard_info.source.json';
SKeyboardInfoDistSchemaJson = 'keyboard_info.distribution.json';
var
GCallback: TProjectLogObjectEvent = nil;
GFilename: string;
type TValidateJsonMessageProc = function (offset: Int64; message: PAnsiChar): BOOL; stdcall;
// TODO: dynamically load this
function ValidateJsonFile(pwszSchemaFile, pwszJsonFile: PWideChar; MessageProc: TValidateJsonMessageProc): BOOL;
stdcall; external kmcmpdll_lib;
function ValidateMessageProc(offset: Int64; message: PAnsiChar): BOOL; stdcall;
begin
GCallback(plsInfo, GFilename, string(AnsiString(message)), 0, 0);
Result := TRUE;
end;
constructor TValidateKeyboardInfo.Create(AJsonFile: string; ASilent: Boolean);
begin
inherited Create;
FJsonFile := AJsonFile;
FSilent := ASilent;
end;
function TValidateKeyboardInfo.DoFieldValidation: Boolean;
var
alangs: TJSONArray;
langs: TJSONValue;
i: Integer;
olangs: TJSONObject;
msg: string;
begin
if not LoadJsonFile then
Exit(False);
// Test that language ids are valid and canonical
langs := json.Values[TKeyboardInfoFile.SLanguages];
if not Assigned(langs) then
Exit(True);
Result := True;
if langs is TJSONArray then
begin
alangs := langs as TJSONArray;
for i := 0 to alangs.Count - 1 do
with TBCP47Tag.Create(alangs.Items[i].Value) do
try
if not IsValid(False, msg) then
Result := Failed(msg);
if not TCanonicalLanguageCodeUtils.IsCanonical(Tag, msg, False, False) then
Warning(msg);
finally
Free;
end;
end
else
begin
olangs := langs as TJSONObject;
for i := 0 to olangs.Count - 1 do
with TBCP47Tag.Create(olangs.Pairs[i].JsonString.Value) do
try
if not IsValid(False, msg) then
Result := Failed(msg);
if not TCanonicalLanguageCodeUtils.IsCanonical(Tag, msg, False, False) then
Warning(msg);
finally
Free;
end;
end;
end;
function TValidateKeyboardInfo.Failed(message: string): Boolean;
begin
GCallback(plsError, FJsonFile, Message, 0, 0);
Result := False;
end;
procedure TValidateKeyboardInfo.Hint(message: string);
begin
GCallback(plsHint, FJsonFile, Message, 0, 0);
end;
procedure TValidateKeyboardInfo.Info(message: string);
begin
GCallback(plsInfo, FJsonFile, Message, 0, 0);
end;
function TValidateKeyboardInfo.LoadJsonFile: Boolean;
begin
try
with TStringStream.Create('', TEncoding.UTF8) do
try
LoadFromFile(FJsonFile);
json := TJSONObject.ParseJsonValue(DataString) as TJSONObject;
finally
Free;
end;
except
on E:Exception do
Exit(Failed(E.Message));
end;
Result := Assigned(json);
end;
procedure TValidateKeyboardInfo.Warning(message: string);
begin
GCallback(plsWarning, FJsonFile, Message, 0, 0);
end;
class function TValidateKeyboardInfo.Execute(JsonFile, JsonSchemaPath: string; FDistribution, FSilent: Boolean; FCallback: TProjectLogObjectEvent): Boolean;
var
SchemaFile: string;
t: TValidateKeyboardInfo;
begin
GCallback := FCallback;
GFilename := JsonFile;
if FDistribution
then SchemaFile := JsonSchemaPath + SKeyboardInfoDistSchemaJson
else SchemaFile := JsonSchemaPath + SKeyboardInfoSourceSchemaJson;
Result := ValidateJsonFile(PWideChar(SchemaFile), PWideChar(JsonFile), ValidateMessageProc);
if Result then
begin
t := TValidateKeyboardInfo.Create(JsonFile, FSilent);
try
Result := t.DoFieldValidation;
finally
t.Free;
end;
end;
if Result
then GCallback(plsSuccess, JsonFile, 'File '+JsonFile+' validated successfully.', 0, 0)
else GCallback(plsFailure, JsonFile, 'File '+JsonFile+' has errors.', 0, 0);
end;
end.