Skip to content

Commit ca760ca

Browse files
committed
Refactor word repo/service balance
1 parent 5ad575b commit ca760ca

File tree

10 files changed

+107
-144
lines changed

10 files changed

+107
-144
lines changed

Backend.Tests/Controllers/LiftControllerTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -416,7 +416,7 @@ public async Task TestDeletedWordsExportToLift()
416416
word.Vernacular = "updated";
417417

418418
await _wordService.Update(_projId, UserId, wordToUpdate.Id, word);
419-
await _wordService.DeleteFrontierWord(_projId, UserId, wordToDelete.Id);
419+
await _wordService.MakeFrontierDeleted(_projId, UserId, wordToDelete.Id);
420420

421421
_liftService.SetExportInProgress(UserId, ExportId);
422422
await _liftController.CreateLiftExportThenSignal(_projId, UserId, ExportId);

Backend.Tests/Mocks/WordRepositoryMock.cs

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -127,19 +127,20 @@ public Task<List<Word>> AddFrontier(List<Word> words)
127127
return Task.FromResult(words);
128128
}
129129

130-
public Task<bool> DeleteFrontier(string projectId, string wordId)
130+
public Task<Word?> DeleteFrontier(string projectId, string wordId, string? fileName = null)
131131
{
132-
var origLength = _frontier.Count;
133-
_frontier.RemoveAll(word => word.ProjectId == projectId && word.Id == wordId);
134-
return Task.FromResult(origLength != _frontier.Count);
135-
}
132+
var index = _frontier.FindIndex(
133+
w => w.ProjectId == projectId && w.Id == wordId &&
134+
(fileName is null || w.Audio.Any(a => a.FileName == fileName)));
136135

137-
public Task<long> DeleteFrontier(string projectId, List<string> wordIds)
138-
{
139-
long deletedCount = 0;
140-
wordIds.ForEach(id => deletedCount += _frontier.RemoveAll(
141-
word => word.ProjectId == projectId && word.Id == id));
142-
return Task.FromResult(deletedCount);
136+
if (index == -1)
137+
{
138+
return Task.FromResult<Word?>(null);
139+
}
140+
141+
var word = _frontier[index];
142+
_frontier.RemoveAt(index);
143+
return Task.FromResult<Word?>(word);
143144
}
144145

145146
public Task<Word> Add(Word word)

Backend.Tests/Services/WordServiceTests.cs

Lines changed: 22 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
using System.Collections.Generic;
21
using System.Linq;
32
using Backend.Tests.Mocks;
43
using BackendFramework.Interfaces;
@@ -28,23 +27,22 @@ public void Setup()
2827
[Test]
2928
public void TestCreateAddsUserId()
3029
{
31-
var word = _wordService.Create(UserId, new Word { EditedBy = new List<string> { "other" } }).Result;
30+
var word = _wordService.Create(UserId, new Word { EditedBy = ["other"] }).Result;
3231
Assert.That(word.EditedBy, Has.Count.EqualTo(2));
3332
Assert.That(word.EditedBy.Last(), Is.EqualTo(UserId));
3433
}
3534

3635
[Test]
3736
public void TestCreateDoesNotAddDuplicateUserId()
3837
{
39-
var word = _wordService.Create(UserId, new Word { EditedBy = new List<string> { UserId } }).Result;
38+
var word = _wordService.Create(UserId, new Word { EditedBy = [UserId] }).Result;
4039
Assert.That(word.EditedBy, Has.Count.EqualTo(1));
4140
}
4241

4342
[Test]
4443
public void TestCreateMultipleWords()
4544
{
46-
_ = _wordService.Create(
47-
UserId, new List<Word> { new() { ProjectId = ProjId }, new() { ProjectId = ProjId } }).Result;
45+
_ = _wordService.Create(UserId, [new() { ProjectId = ProjId }, new() { ProjectId = ProjId }]).Result;
4846
Assert.That(_wordRepo.GetAllWords(ProjId).Result, Has.Count.EqualTo(2));
4947
Assert.That(_wordRepo.GetFrontier(ProjId).Result, Has.Count.EqualTo(2));
5048
}
@@ -54,38 +52,38 @@ public void TestDeleteAudioBadInputNull()
5452
{
5553
var fileName = "audio.mp3";
5654
var wordInFrontier = _wordRepo.Create(
57-
new Word() { Audio = new() { new() { FileName = fileName } }, ProjectId = ProjId }).Result;
58-
Assert.That(_wordService.Delete("non-project-id", UserId, wordInFrontier.Id, fileName).Result, Is.Null);
59-
Assert.That(_wordService.Delete(ProjId, UserId, "non-word-id", fileName).Result, Is.Null);
60-
Assert.That(_wordService.Delete(ProjId, UserId, wordInFrontier.Id, "non-file-name").Result, Is.Null);
55+
new Word() { Audio = [new() { FileName = fileName }], ProjectId = ProjId }).Result;
56+
Assert.That(_wordService.DeleteAudio("non-proj-id", UserId, wordInFrontier.Id, fileName).Result, Is.Null);
57+
Assert.That(_wordService.DeleteAudio(ProjId, UserId, "non-word-id", fileName).Result, Is.Null);
58+
Assert.That(_wordService.DeleteAudio(ProjId, UserId, wordInFrontier.Id, "non-file-name").Result, Is.Null);
6159
}
6260

6361
[Test]
6462
public void TestDeleteAudioNotInFrontierNull()
6563
{
6664
var fileName = "audio.mp3";
6765
var wordNotInFrontier = _wordRepo.Add(
68-
new() { Audio = new() { new() { FileName = fileName } }, ProjectId = ProjId }).Result;
69-
Assert.That(_wordService.Delete(ProjId, UserId, wordNotInFrontier.Id, fileName).Result, Is.Null);
66+
new() { Audio = [new() { FileName = fileName }], ProjectId = ProjId }).Result;
67+
Assert.That(_wordService.DeleteAudio(ProjId, UserId, wordNotInFrontier.Id, fileName).Result, Is.Null);
7068
}
7169

7270
[Test]
7371
public void TestDeleteAudio()
7472
{
7573
var fileName = "audio.mp3";
7674
var wordInFrontier = _wordRepo.Create(
77-
new Word() { Audio = new() { new() { FileName = fileName } }, ProjectId = ProjId }).Result;
78-
var result = _wordService.Delete(ProjId, UserId, wordInFrontier.Id, fileName).Result;
75+
new Word() { Audio = [new() { FileName = fileName }], ProjectId = ProjId }).Result;
76+
var result = _wordService.DeleteAudio(ProjId, UserId, wordInFrontier.Id, fileName).Result;
7977
Assert.That(result!.EditedBy.Last(), Is.EqualTo(UserId));
8078
Assert.That(result!.History.Last(), Is.EqualTo(wordInFrontier.Id));
8179
Assert.That(_wordRepo.IsInFrontier(ProjId, result.Id).Result, Is.True);
8280
Assert.That(_wordRepo.IsInFrontier(ProjId, wordInFrontier.Id).Result, Is.False);
8381
}
8482

8583
[Test]
86-
public void TestUpdateNotInFrontierFalse()
84+
public void TestUpdateNotInFrontierNull()
8785
{
88-
Assert.That(_wordService.Update(ProjId, UserId, WordId, new Word()).Result, Is.False);
86+
Assert.That(_wordService.Update(ProjId, UserId, WordId, new Word()).Result, Is.Null);
8987
}
9088

9189
[Test]
@@ -95,7 +93,7 @@ public void TestUpdateReplacesFrontierWord()
9593
Assert.That(word, Is.Not.Null);
9694
var oldId = word.Id;
9795
word.Vernacular = "NewVern";
98-
Assert.That(_wordService.Update(ProjId, UserId, oldId, word).Result, Is.True);
96+
Assert.That(_wordService.Update(ProjId, UserId, oldId, word).Result, Is.Not.Null);
9997
var frontier = _wordRepo.GetFrontier(ProjId).Result;
10098
Assert.That(frontier, Has.Count.EqualTo(1));
10199
var newWord = frontier.First();
@@ -126,8 +124,7 @@ public void TestUpdateUsingCitationForm()
126124
public void TestRestoreFrontierWordsMissingWordFalse()
127125
{
128126
var word = _wordRepo.Add(new Word { ProjectId = ProjId }).Result;
129-
Assert.That(_wordService.RestoreFrontierWords(
130-
ProjId, new List<string> { "NotAnId", word.Id }).Result, Is.False);
127+
Assert.That(_wordService.RestoreFrontierWords(ProjId, ["NotAnId", word.Id]).Result, Is.False);
131128
}
132129

133130
[Test]
@@ -136,8 +133,8 @@ public void TestRestoreFrontierWordsFrontierWordFalse()
136133
var wordNoFrontier = _wordRepo.Add(new Word { ProjectId = ProjId }).Result;
137134
var wordYesFrontier = _wordRepo.Create(new Word { ProjectId = ProjId }).Result;
138135
Assert.That(_wordRepo.GetFrontier(ProjId).Result, Has.Count.EqualTo(1));
139-
Assert.That(_wordService.RestoreFrontierWords(
140-
ProjId, new List<string> { wordNoFrontier.Id, wordYesFrontier.Id }).Result, Is.False);
136+
Assert.That(
137+
_wordService.RestoreFrontierWords(ProjId, [wordNoFrontier.Id, wordYesFrontier.Id]).Result, Is.False);
141138
}
142139

143140
[Test]
@@ -146,8 +143,7 @@ public void TestRestoreFrontierWordsTrue()
146143
var word1 = _wordRepo.Add(new Word { ProjectId = ProjId }).Result;
147144
var word2 = _wordRepo.Add(new Word { ProjectId = ProjId }).Result;
148145
Assert.That(_wordRepo.GetFrontier(ProjId).Result, Is.Empty);
149-
Assert.That(_wordService.RestoreFrontierWords(
150-
ProjId, new List<string> { word1.Id, word2.Id }).Result, Is.True);
146+
Assert.That(_wordService.RestoreFrontierWords(ProjId, [word1.Id, word2.Id]).Result, Is.True);
151147
Assert.That(_wordRepo.GetFrontier(ProjId).Result, Has.Count.EqualTo(2));
152148
}
153149

@@ -187,7 +183,7 @@ public void TestFindContainingWordSameVernSubsetSense()
187183

188184
// Sense of new word is subset of one sense of old word.
189185
var oldSense = Util.RandomSense();
190-
newWord.Senses = new List<Sense> { oldSense.Clone() };
186+
newWord.Senses = [oldSense.Clone()];
191187
oldSense.Definitions.Add(Util.RandomDefinition());
192188
oldSense.Glosses.Add(Util.RandomGloss());
193189
oldWord.Senses.Add(oldSense);
@@ -208,9 +204,9 @@ public void TestFindContainingWordSameVernEmptySensesDiffDoms()
208204
// New word sense with no definitions and blank gloss.
209205
var newSense = oldWord.Senses.First().Clone();
210206
newSense.Definitions.Clear();
211-
newSense.Glosses = new List<Gloss> { new Gloss() };
207+
newSense.Glosses = [new Gloss()];
212208
newSense.SemanticDomains.Add(Util.RandomSemanticDomain());
213-
newWord.Senses = new List<Sense> { newSense };
209+
newWord.Senses = [newSense];
214210

215211
var dupId = _wordService.FindContainingWord(newWord).Result;
216212
Assert.That(dupId, Is.Null);
@@ -228,7 +224,7 @@ public void TestFindContainingWordSameVernEmptySensesSameDoms()
228224
var emptySense = Util.RandomSense();
229225
emptySense.Definitions.Clear();
230226
emptySense.Glosses.Clear();
231-
newWord.Senses = new List<Sense> { emptySense.Clone() };
227+
newWord.Senses = [emptySense.Clone()];
232228
emptySense.SemanticDomains.Add(Util.RandomSemanticDomain());
233229
oldWord.Senses.Add(emptySense);
234230
oldWord = _wordRepo.Create(oldWord).Result;

Backend/Controllers/AudioController.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ public async Task<IActionResult> DeleteAudioFile(string projectId, string wordId
177177
return new UnsupportedMediaTypeResult();
178178
}
179179

180-
var newWord = await _wordService.Delete(projectId, userId, wordId, fileName);
180+
var newWord = await _wordService.DeleteAudio(projectId, userId, wordId, fileName);
181181
if (newWord is not null)
182182
{
183183
return Ok(newWord.Id);

Backend/Controllers/WordController.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ public async Task<IActionResult> DeleteFrontierWord(string projectId, string wor
4343
}
4444
var userId = _permissionService.GetUserId(HttpContext);
4545

46-
var deletedWordId = await _wordService.DeleteFrontierWord(projectId, userId, wordId);
46+
var deletedWordId = await _wordService.MakeFrontierDeleted(projectId, userId, wordId);
4747
return deletedWordId is null ? NotFound() : Ok();
4848
}
4949

Backend/Interfaces/IWordRepository.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ public interface IWordRepository
2121
Task<List<Word>> GetFrontierWithVernacular(string projectId, string vernacular);
2222
Task<Word> AddFrontier(Word word);
2323
Task<List<Word>> AddFrontier(List<Word> words);
24-
Task<bool> DeleteFrontier(string projectId, string wordId);
25-
Task<long> DeleteFrontier(string projectId, List<string> wordIds);
24+
Task<Word?> DeleteFrontier(string projectId, string wordId, string? fileName = null);
2625
}
2726
}

Backend/Interfaces/IWordService.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@ public interface IWordService
88
{
99
Task<Word> Create(string userId, Word word);
1010
Task<List<Word>> Create(string userId, List<Word> words);
11-
Task<bool> Update(string projectId, string userId, string wordId, Word word);
12-
Task<bool> Delete(string projectId, string userId, string wordId);
13-
Task<Word?> Delete(string projectId, string userId, string wordId, string fileName);
14-
Task<string?> DeleteFrontierWord(string projectId, string userId, string wordId);
11+
Task<string?> Update(string projectId, string userId, string wordId, Word word);
12+
Task<Word?> DeleteAudio(string projectId, string userId, string wordId, string fileName);
13+
Task<Word?> DeleteFrontierWord(string projectId, string wordId);
14+
Task<int> DeleteFrontierWords(string projectId, List<string> wordIds);
15+
Task<string?> MakeFrontierDeleted(string projectId, string userId, string wordId);
1516
Task<bool> RestoreFrontierWords(string projectId, List<string> wordIds);
1617
Task<string?> FindContainingWord(Word word);
1718
}

Backend/Repositories/WordRepository.cs

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,16 @@ private static FilterDefinition<Word> GetProjectWordFilter(string projectId, str
3939
return filterDef.And(filterDef.Eq(w => w.ProjectId, projectId), filterDef.Eq(w => w.Id, wordId));
4040
}
4141

42+
/// <summary> Creates a mongo filter for project words with specified wordId and audio. </summary>
43+
private static FilterDefinition<Word> GetProjectWordFilter(string projectId, string wordId, string fileName)
44+
{
45+
var filterDef = new FilterDefinitionBuilder<Word>();
46+
return filterDef.And(
47+
filterDef.Eq(w => w.ProjectId, projectId),
48+
filterDef.Eq(w => w.Id, wordId),
49+
filterDef.ElemMatch(w => w.Audio, a => a.FileName == fileName));
50+
}
51+
4252
/// <summary> Creates a mongo filter for words in a specified project with specified wordIds. </summary>
4353
private static FilterDefinition<Word> GetProjectWordsFilter(string projectId, List<string> wordIds)
4454
{
@@ -251,22 +261,13 @@ public async Task<List<Word>> AddFrontier(List<Word> words)
251261

252262
/// <summary> Removes <see cref="Word"/> from the Frontier with specified wordId and projectId </summary>
253263
/// <returns> A bool: success of operation </returns>
254-
public async Task<bool> DeleteFrontier(string projectId, string wordId)
264+
public async Task<Word?> DeleteFrontier(string projectId, string wordId, string? fileName = null)
255265
{
256266
using var activity = OtelService.StartActivityWithTag(otelTagName, "deleting a word from Frontier");
257267

258-
var deleted = await _frontier.DeleteOneAsync(GetProjectWordFilter(projectId, wordId));
259-
return deleted.DeletedCount > 0;
260-
}
261-
262-
/// <summary> Removes <see cref="Word"/>s from the Frontier with specified wordIds and projectId </summary>
263-
/// <returns> Number of words deleted </returns>
264-
public async Task<long> DeleteFrontier(string projectId, List<string> wordIds)
265-
{
266-
using var activity = OtelService.StartActivityWithTag(otelTagName, "deleting words from Frontier");
267-
268-
var deleted = await _frontier.DeleteManyAsync(GetProjectWordsFilter(projectId, wordIds));
269-
return deleted.DeletedCount;
268+
return fileName is null
269+
? await _frontier.FindOneAndDeleteAsync(GetProjectWordFilter(projectId, wordId))
270+
: await _frontier.FindOneAndDeleteAsync(GetProjectWordFilter(projectId, wordId, fileName));
270271
}
271272
}
272273
}

Backend/Services/MergeService.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ private async Task<Word> MergePrepParent(string projectId, MergeWords mergeWords
120120
private async Task<long> MergeDeleteChildren(string projectId, MergeWords mergeWords)
121121
{
122122
var childIds = mergeWords.Children.Select(c => c.SrcWordId).ToList();
123-
return await _wordRepo.DeleteFrontier(projectId, childIds);
123+
return await _wordService.DeleteFrontierWords(projectId, childIds);
124124
}
125125

126126
/// <summary>
@@ -160,7 +160,7 @@ public async Task<bool> UndoMerge(string projectId, string userId, MergeUndoIds
160160
}
161161
foreach (var parentId in ids.ParentIds)
162162
{
163-
await _wordService.DeleteFrontierWord(projectId, userId, parentId);
163+
await _wordService.MakeFrontierDeleted(projectId, userId, parentId);
164164
}
165165
return true;
166166
}

0 commit comments

Comments
 (0)