-
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
* Implement UpdateWritingSystem(before, after) * mark up string diff as allowing null strings --------- Co-authored-by: Kevin Hahn <[email protected]>
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
using System.Diagnostics.CodeAnalysis; | ||
using MiniLcm.Models; | ||
using SIL.LCModel; | ||
using SIL.LCModel.Core.WritingSystems; | ||
using SIL.LCModel.DomainServices; | ||
using SIL.WritingSystems; | ||
|
||
namespace FwDataMiniLcmBridge.Api.UpdateProxy; | ||
|
||
public record UpdateWritingSystemProxy : WritingSystem | ||
{ | ||
private readonly CoreWritingSystemDefinition _origLcmWritingSystem; | ||
private readonly CoreWritingSystemDefinition _workingLcmWritingSystem; | ||
private readonly FwDataMiniLcmApi _lexboxLcmApi; | ||
|
||
[SetsRequiredMembers] | ||
public UpdateWritingSystemProxy(CoreWritingSystemDefinition lcmWritingSystem, FwDataMiniLcmApi lexboxLcmApi) | ||
{ | ||
_origLcmWritingSystem = lcmWritingSystem; | ||
_workingLcmWritingSystem = new CoreWritingSystemDefinition(lcmWritingSystem, cloneId: true); | ||
base.Abbreviation = Abbreviation = _origLcmWritingSystem.Abbreviation ?? ""; | ||
base.Name = Name = _origLcmWritingSystem.LanguageName ?? ""; | ||
base.Font = Font = _origLcmWritingSystem.DefaultFontName ?? ""; | ||
_lexboxLcmApi = lexboxLcmApi; | ||
} | ||
|
||
public void CommitUpdate(LcmCache cache) | ||
{ | ||
if (_workingLcmWritingSystem.Id == _origLcmWritingSystem.Id) | ||
{ | ||
cache.ServiceLocator.WritingSystemManager.Set(_workingLcmWritingSystem); | ||
} | ||
else | ||
{ | ||
// Changing the ID of a writing system requires LCM to do a lot of work, so only go through that process if absolutely required | ||
WritingSystemServices.MergeWritingSystems(cache, _workingLcmWritingSystem, _origLcmWritingSystem); | ||
} | ||
} | ||
|
||
public override required WritingSystemId WsId | ||
{ | ||
get => _workingLcmWritingSystem.Id; | ||
set => _workingLcmWritingSystem.Id = value; | ||
} | ||
|
||
public override required string Name | ||
{ | ||
get => _workingLcmWritingSystem.LanguageName; | ||
set { } // Silently do nothing; name should be derived from WsId at all times, so if the name should change then so should the WsId | ||
} | ||
|
||
public override required string Abbreviation | ||
{ | ||
get => _workingLcmWritingSystem.Abbreviation; | ||
set => _workingLcmWritingSystem.Abbreviation = value; | ||
} | ||
|
||
public override required string Font | ||
{ | ||
get => _workingLcmWritingSystem.DefaultFontName; | ||
set | ||
{ | ||
if (value != _workingLcmWritingSystem.DefaultFontName) | ||
{ | ||
_workingLcmWritingSystem.DefaultFont = new FontDefinition(value); | ||
} | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
using SystemTextJsonPatch.Operations; | ||
|
||
namespace MiniLcm.SyncHelpers; | ||
|
||
public static class SimpleStringDiff | ||
{ | ||
public static IEnumerable<Operation<T>> GetStringDiff<T>(string path, | ||
string? before, | ||
string? after) where T : class | ||
{ | ||
if (before == after) yield break; | ||
if (after is null) yield return new Operation<T>("remove", $"/{path}", null); | ||
else if (before is null) yield return new Operation<T>("add", $"/{path}", null); | ||
else yield return new Operation<T>("replace", $"/{path}", null, after); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
using MiniLcm.Models; | ||
using SystemTextJsonPatch; | ||
|
||
namespace MiniLcm.SyncHelpers; | ||
|
||
public static class WritingSystemSync | ||
{ | ||
public static async Task<int> Sync(WritingSystem[] currentWritingSystems, | ||
WritingSystem[] previousWritingSystems, | ||
IMiniLcmApi api) | ||
{ | ||
return await DiffCollection.Diff(api, | ||
previousWritingSystems, | ||
currentWritingSystems, | ||
ws => (ws.WsId, ws.Type), | ||
async (api, currentWs) => | ||
{ | ||
await api.CreateWritingSystem(currentWs.Type, currentWs); | ||
return 1; | ||
}, | ||
async (api, previousWs) => | ||
Check warning on line 21 in backend/FwLite/MiniLcm/SyncHelpers/WritingSystemSync.cs GitHub Actions / Build FwHeadless / publish-fw-headless
Check warning on line 21 in backend/FwLite/MiniLcm/SyncHelpers/WritingSystemSync.cs GitHub Actions / Build FW Lite and run tests
Check warning on line 21 in backend/FwLite/MiniLcm/SyncHelpers/WritingSystemSync.cs GitHub Actions / Publish FW Lite app for Mac
Check warning on line 21 in backend/FwLite/MiniLcm/SyncHelpers/WritingSystemSync.cs GitHub Actions / Publish FW Lite app for Mac
Check warning on line 21 in backend/FwLite/MiniLcm/SyncHelpers/WritingSystemSync.cs GitHub Actions / Publish FW Lite app for Linux
Check warning on line 21 in backend/FwLite/MiniLcm/SyncHelpers/WritingSystemSync.cs GitHub Actions / Publish FW Lite app for Linux
Check warning on line 21 in backend/FwLite/MiniLcm/SyncHelpers/WritingSystemSync.cs GitHub Actions / Publish FW Lite app for Windows
Check warning on line 21 in backend/FwLite/MiniLcm/SyncHelpers/WritingSystemSync.cs GitHub Actions / Publish FW Lite app for Windows
|
||
{ | ||
// await api.DeleteWritingSystem(previousWs.Id); // Deleting writing systems is dangerous as it causes cascading data deletion. Needs careful thought. | ||
// TODO: should we throw an exception? | ||
return 0; | ||
}, | ||
async (api, previousWs, currentWs) => | ||
{ | ||
return await Sync(currentWs, previousWs, api); | ||
}); | ||
} | ||
|
||
public static async Task<int> Sync(WritingSystem afterWs, WritingSystem beforeWs, IMiniLcmApi api) | ||
{ | ||
var updateObjectInput = WritingSystemDiffToUpdate(beforeWs, afterWs); | ||
if (updateObjectInput is not null) await api.UpdateWritingSystem(afterWs.WsId, afterWs.Type, updateObjectInput); | ||
return updateObjectInput is null ? 0 : 1; | ||
} | ||
|
||
public static UpdateObjectInput<WritingSystem>? WritingSystemDiffToUpdate(WritingSystem previousWritingSystem, WritingSystem currentWritingSystem) | ||
{ | ||
JsonPatchDocument<WritingSystem> patchDocument = new(); | ||
if (previousWritingSystem.WsId != currentWritingSystem.WsId) | ||
{ | ||
// TODO: Throw? Or silently ignore? | ||
throw new InvalidOperationException($"Tried to change immutable WsId from {previousWritingSystem.WsId} to {currentWritingSystem.WsId}"); | ||
} | ||
patchDocument.Operations.AddRange(SimpleStringDiff.GetStringDiff<WritingSystem>(nameof(WritingSystem.Name), | ||
previousWritingSystem.Name, | ||
currentWritingSystem.Name)); | ||
patchDocument.Operations.AddRange(SimpleStringDiff.GetStringDiff<WritingSystem>(nameof(WritingSystem.Abbreviation), | ||
previousWritingSystem.Abbreviation, | ||
currentWritingSystem.Abbreviation)); | ||
patchDocument.Operations.AddRange(SimpleStringDiff.GetStringDiff<WritingSystem>(nameof(WritingSystem.Font), | ||
previousWritingSystem.Font, | ||
currentWritingSystem.Font)); | ||
// TODO: Exemplars, Order, and do we need DeletedAt? | ||
if (patchDocument.Operations.Count == 0) return null; | ||
return new UpdateObjectInput<WritingSystem>(patchDocument); | ||
} | ||
} |