Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 11 additions & 18 deletions backend/FwLite/FwDataMiniLcmBridge/Api/FwDataMiniLcmApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,28 +85,24 @@ internal int GetWritingSystemHandle(WritingSystemId ws, WritingSystemType? type

public Task<WritingSystems> GetWritingSystems()
{
var currentVernacularWs = WritingSystemContainer
.CurrentVernacularWritingSystems
.Select(ws => ws.Id).ToHashSet();
var currentAnalysisWs = WritingSystemContainer
.CurrentAnalysisWritingSystems
.Select(ws => ws.Id).ToHashSet();
var writingSystems = new WritingSystems
{
Vernacular = WritingSystemContainer.CurrentVernacularWritingSystems.Select((definition, index) =>
FromLcmWritingSystem(definition, index, WritingSystemType.Vernacular)).ToArray(),
FromLcmWritingSystem(definition, WritingSystemType.Vernacular, index)).ToArray(),
Analysis = WritingSystemContainer.CurrentAnalysisWritingSystems.Select((definition, index) =>
FromLcmWritingSystem(definition, index, WritingSystemType.Analysis)).ToArray()
FromLcmWritingSystem(definition, WritingSystemType.Analysis, index)).ToArray()
};
CompleteExemplars(writingSystems);
return Task.FromResult(writingSystems);
}

private WritingSystem FromLcmWritingSystem(CoreWritingSystemDefinition ws, int index, WritingSystemType type)
private WritingSystem FromLcmWritingSystem(CoreWritingSystemDefinition ws, WritingSystemType type, int index = default)
{
return new WritingSystem
{
Id = Guid.Empty,
// todo: Order probably shouldn't be relied on in fwdata, because it's implicit,
// so it probably shouldn't be used or set at all
Order = index,
Type = type,
//todo determine current and create a property for that.
Expand All @@ -118,15 +114,12 @@ private WritingSystem FromLcmWritingSystem(CoreWritingSystemDefinition ws, int i
};
}

public async Task<WritingSystem?> GetWritingSystem(WritingSystemId id, WritingSystemType type)
public Task<WritingSystem?> GetWritingSystem(WritingSystemId id, WritingSystemType type)
{
var writingSystems = await GetWritingSystems();
return type switch
{
WritingSystemType.Vernacular => writingSystems.Vernacular.FirstOrDefault(ws => ws.WsId == id),
WritingSystemType.Analysis => writingSystems.Analysis.FirstOrDefault(ws => ws.WsId == id),
_ => throw new ArgumentOutOfRangeException(nameof(type), type, null)
};
var lcmWs = Cache.GetCoreWritingSystem(id, type);
if (lcmWs is null) return Task.FromResult<WritingSystem?>(null);
var ws = FromLcmWritingSystem(lcmWs, type);
return Task.FromResult<WritingSystem?>(ws);
}

internal void CompleteExemplars(WritingSystems writingSystems)
Expand Down Expand Up @@ -187,7 +180,7 @@ await Cache.DoUsingNewOrCurrentUOW("Create Writing System",
WritingSystemType.Vernacular => WritingSystemContainer.CurrentVernacularWritingSystems.Count,
_ => throw new ArgumentOutOfRangeException(nameof(type), type, null)
} - 1;
return FromLcmWritingSystem(ws, index, type);
return FromLcmWritingSystem(ws, type, index);
}

public async Task<WritingSystem> UpdateWritingSystem(WritingSystemId id, WritingSystemType type, UpdateObjectInput<WritingSystem> update)
Expand Down
24 changes: 15 additions & 9 deletions backend/FwLite/FwDataMiniLcmBridge/Api/LcmHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -166,22 +166,22 @@ internal static WritingSystemId GetWritingSystemId(this LcmCache cache, int ws)
return cache.ServiceLocator.WritingSystemManager.Get(ws).Id;
}

internal static int GetWritingSystemHandle(this LcmCache cache, WritingSystemId ws, WritingSystemType? type = null)
internal static CoreWritingSystemDefinition GetCoreWritingSystem(this LcmCache cache, WritingSystemId wsId, WritingSystemType? type = null)
{
var wsContainer = cache.ServiceLocator.WritingSystems;
if (ws == "default")
if (wsId == default)
{
return type switch
{
WritingSystemType.Analysis => wsContainer.DefaultAnalysisWritingSystem.Handle,
WritingSystemType.Vernacular => wsContainer.DefaultVernacularWritingSystem.Handle,
WritingSystemType.Analysis => wsContainer.DefaultAnalysisWritingSystem,
WritingSystemType.Vernacular => wsContainer.DefaultVernacularWritingSystem,
_ => throw new ArgumentOutOfRangeException(nameof(type), type, null)
};
}

if (!cache.ServiceLocator.WritingSystemManager.TryGet(ws.Code, out var lcmWs))
if (!cache.ServiceLocator.WritingSystemManager.TryGet(wsId.Code, out var lcmWs))
{
throw new NullReferenceException($"unable to find writing system with id '{ws.Code}'");
throw new NullReferenceException($"unable to find writing system with id '{wsId.Code}'");
}
if (lcmWs is not null && type is not null)
{
Expand All @@ -193,15 +193,21 @@ internal static int GetWritingSystemHandle(this LcmCache cache, WritingSystemId
};
if (!validWs.Contains(lcmWs))
{
throw new InvalidOperationException($"Writing system {ws} is not of the requested type: {type}.");
throw new InvalidOperationException($"Writing system {wsId} is not of the requested type: {type}.");
}
}
if (lcmWs is null)
{
throw new NullReferenceException($"unable to find writing system with id {ws}");
throw new NullReferenceException($"unable to find writing system with id {wsId}");
}

return lcmWs.Handle;
return lcmWs;
}

internal static int GetWritingSystemHandle(this LcmCache cache, WritingSystemId wsId, WritingSystemType? type = null)
{
var ws = GetCoreWritingSystem(cache, wsId, type);
return ws.Handle;
}

internal static string PickText(this ICmObject obj, ITsMultiString multiString, string ws)
Expand Down
8 changes: 1 addition & 7 deletions backend/FwLite/LcmCrdt/CrdtMiniLcmApi.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System.Data;
using Gridify;
using SIL.Harmony;
using SIL.Harmony.Changes;
using LcmCrdt.Changes;
Expand All @@ -8,7 +7,6 @@
using LcmCrdt.FullTextSearch;
using LcmCrdt.MediaServer;
using LcmCrdt.Objects;
using LcmCrdt.Utils;
using LinqToDB;
using LinqToDB.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
Expand All @@ -18,7 +16,6 @@
using SIL.Harmony.Core;
using MiniLcm.Culture;
using MiniLcm.Media;
using SystemTextJsonPatch;

namespace LcmCrdt;

Expand Down Expand Up @@ -68,10 +65,7 @@ private void AssertWritable()
public async Task<WritingSystems> GetWritingSystems()
{
await using var repo = await repoFactory.CreateRepoAsync();
var systems = await repo.WritingSystems
.OrderBy(ws => ws.Order)
.ThenBy(ws => ws.WsId)
.ToArrayAsync();
var systems = await repo.WritingSystemsOrdered.ToArrayAsync();
return new WritingSystems
{
Analysis = [.. systems.Where(ws => ws.Type == WritingSystemType.Analysis)],
Expand Down
9 changes: 5 additions & 4 deletions backend/FwLite/LcmCrdt/Data/MiniLcmRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
namespace LcmCrdt.Data;

public class MiniLcmRepositoryFactory(
Microsoft.EntityFrameworkCore.IDbContextFactory<LcmCrdtDbContext> dbContextFactory,
IDbContextFactory<LcmCrdtDbContext> dbContextFactory,
IServiceProvider serviceProvider,
EntrySearchServiceFactory? entrySearchServiceFactory = null)
{
Expand Down Expand Up @@ -67,6 +67,7 @@ public void Dispose()
public IQueryable<Sense> Senses => dbContext.Senses;
public IQueryable<ExampleSentence> ExampleSentences => dbContext.ExampleSentences;
public IQueryable<WritingSystem> WritingSystems => dbContext.WritingSystems;
public IQueryable<WritingSystem> WritingSystemsOrdered => dbContext.WritingSystemsOrdered;
public IQueryable<SemanticDomain> SemanticDomains => dbContext.SemanticDomains;
public IQueryable<PartOfSpeech> PartsOfSpeech => dbContext.PartsOfSpeech;
public IQueryable<Publication> Publications => dbContext.Publications;
Expand All @@ -81,14 +82,14 @@ public void Dispose()
return type switch
{
WritingSystemType.Analysis => _defaultAnalysisWs ??=
await AsyncExtensions.FirstOrDefaultAsync(dbContext.WritingSystems, ws => ws.Type == type),
await AsyncExtensions.FirstOrDefaultAsync(WritingSystemsOrdered, ws => ws.Type == type),
WritingSystemType.Vernacular => _defaultVernacularWs ??=
await AsyncExtensions.FirstOrDefaultAsync(dbContext.WritingSystems, ws => ws.Type == type),
await AsyncExtensions.FirstOrDefaultAsync(WritingSystemsOrdered, ws => ws.Type == type),
_ => throw new ArgumentOutOfRangeException(nameof(type), type, null)
} ?? throw new NullReferenceException($"Unable to find a default writing system of type {type}");
}

return await AsyncExtensions.FirstOrDefaultAsync(dbContext.WritingSystems, ws => ws.WsId == id && ws.Type == type);
return await AsyncExtensions.FirstOrDefaultAsync(WritingSystemsOrdered, ws => ws.WsId == id && ws.Type == type);
}

public async Task<AddEntryComponentChange> CreateComplexFormComponentChange(
Expand Down
13 changes: 8 additions & 5 deletions backend/FwLite/LcmCrdt/FullTextSearch/EntrySearchService.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
using System.Globalization;
using System.Linq.Expressions;
using System.Text;
using LcmCrdt.Data;
using LinqToDB;
Expand Down Expand Up @@ -139,7 +137,7 @@ public async Task UpdateEntrySearchTable(Guid entryId)

public async Task UpdateEntrySearchTable(Entry entry)
{
var writingSystems = await dbContext.WritingSystems.OrderBy(ws => ws.Order).ToArrayAsync();
var writingSystems = await dbContext.WritingSystemsOrdered.ToArrayAsync();
var record = ToEntrySearchRecord(entry, writingSystems);
await InsertOrUpdateEntrySearchRecord(record, EntrySearchRecordsTable);
}
Expand Down Expand Up @@ -181,7 +179,12 @@ public static async Task UpdateEntrySearchTable(IEnumerable<Entry> entries,
..dbContext.WritingSystems,
..newWritingSystems
];
Array.Sort(writingSystems, (ws1, ws2) => ws1.Order.CompareTo(ws2.Order));
Array.Sort(writingSystems, (ws1, ws2) =>
{
var orderComparison = ws1.Order.CompareTo(ws2.Order);
if (orderComparison != 0) return orderComparison;
return ws1.Id.CompareTo(ws2.Id);
});
var entrySearchRecordsTable = dbContext.GetTable<EntrySearchRecord>();
var searchRecords = entries.Select(entry => ToEntrySearchRecord(entry, writingSystems));
foreach (var entrySearchRecord in searchRecords)
Expand All @@ -200,7 +203,7 @@ public async Task RegenerateEntrySearchTable()
await using var transaction = await dbContext.Database.BeginTransactionAsync();
await EntrySearchRecordsTable.TruncateAsync();

var writingSystems = await dbContext.WritingSystems.OrderBy(ws => ws.Order).ToArrayAsync();
var writingSystems = await dbContext.WritingSystemsOrdered.ToArrayAsync();
await EntrySearchRecordsTable
.BulkCopyAsync(dbContext.Set<Entry>()
.LoadWith(e => e.Senses)
Expand Down
3 changes: 2 additions & 1 deletion backend/FwLite/LcmCrdt/LcmCrdtDbContext.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System.Text.Json;
using LcmCrdt.Data;
using LcmCrdt.FullTextSearch;
using SIL.Harmony;
using SIL.Harmony.Db;
Expand All @@ -17,6 +16,8 @@ IOptions<CrdtConfig> options
{
public DbSet<ProjectData> ProjectData => Set<ProjectData>();
public IQueryable<WritingSystem> WritingSystems => Set<WritingSystem>().AsNoTracking();
public IQueryable<WritingSystem> WritingSystemsOrdered => Set<WritingSystem>().AsNoTracking()
.OrderBy(ws => ws.Order).ThenBy(ws => ws.Id);
public IQueryable<Entry> Entries => Set<Entry>().AsNoTracking();
public IQueryable<ComplexFormComponent> ComplexFormComponents => Set<ComplexFormComponent>().AsNoTracking();
public IQueryable<ComplexFormType> ComplexFormTypes => Set<ComplexFormType>().AsNoTracking();
Expand Down
30 changes: 30 additions & 0 deletions backend/FwLite/MiniLcm.Tests/WritingSystemTestsBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -145,4 +145,34 @@ public async Task InsertWritingSystem_Works()
// we care about the order of return, not the internal Order property
options => options.WithStrictOrdering().Excluding(ws => ws.Order));
}

[Fact]
public async Task CanChangeDefaultWritingSystem()
{
// arrange
var currentDefault = await Api.GetWritingSystem(default, WritingSystemType.Vernacular);
var writingSystems = await Api.GetWritingSystems();
var en = writingSystems.Vernacular.Single(ws => ws.WsId.Code == "en");
currentDefault.Should().BeEquivalentTo(en);
writingSystems.Vernacular.First().Should().BeEquivalentTo(en);

// act
var es = await Api.CreateWritingSystem(new()
{
Id = Guid.NewGuid(),
WsId = "es",
Type = WritingSystemType.Vernacular,
Name = "Spanish",
Abbreviation = "Es",
Font = "Arial"
}, new BetweenPosition<WritingSystemId?>(null, en.WsId));

//assert
var newDefault = await Api.GetWritingSystem(default, WritingSystemType.Vernacular);
newDefault.Should().BeEquivalentTo(es,
options => options.Excluding(ws => ws.Order));
writingSystems = await Api.GetWritingSystems();
writingSystems.Vernacular.First().Should().BeEquivalentTo(es,
options => options.Excluding(ws => ws.Order));
}
}
Loading