mirror of
https://github.com/keymanapp/keyman.git
synced 2026-08-10 10:55:33 +00:00
187 lines
4.6 KiB
ObjectPascal
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.
|