Skip to content

Commit 73cf047

Browse files
committed
[API] LT-8457: Sort References Properly
* Add IStTxtPara.ReferenceForSorting(ISegment, int) to compute a computer-sortable reference string Part of https://jira.sil.org/browse/LT-8457
1 parent f955c06 commit 73cf047

File tree

5 files changed

+129
-6
lines changed

5 files changed

+129
-6
lines changed

src/SIL.LCModel/DomainImpl/ScrTxtPara.cs

+7
Original file line numberDiff line numberDiff line change
@@ -2136,6 +2136,13 @@ public override ITsString Reference(ISegment seg, int ich)
21362136
}
21372137
return Cache.MakeUserTss("unknown"); // should never happen, I think?
21382138
}
2139+
2140+
/// <inheritdoc/>
2141+
public override ITsString ReferenceForSorting(ISegment seg, int ich)
2142+
{
2143+
throw new NotImplementedException();
2144+
}
2145+
21392146
/// ------------------------------------------------------------------------------------
21402147
/// <summary>
21412148
/// Gets the footnote sequence.

src/SIL.LCModel/DomainImpl/StTxtPara.cs

+47
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,53 @@ public virtual ITsString Reference(ISegment seg, int ich)
117117
return bldr.GetString();
118118
}
119119

120+
/// <inheritdoc/>
121+
public virtual ITsString ReferenceForSorting(ISegment seg, int ich)
122+
{
123+
if (!(Owner is IStText stText))
124+
{
125+
return TsStringUtils.EmptyString(Cache.DefaultUserWs);
126+
}
127+
128+
ITsString tssName = null;
129+
// TODO: Abbr
130+
//var fUsingAbbr = false;
131+
//if (stText.Owner is IText text)
132+
//{
133+
// tssName = text.Abbreviation.BestVernacularAnalysisAlternative;
134+
// if (!TsStringUtils.IsNullOrEmpty(tssName))
135+
// {
136+
// fUsingAbbr = true;
137+
// }
138+
//}
139+
tssName = stText.Title.BestVernacularAnalysisAlternative;
140+
var bldr = tssName.GetBldr();
141+
// TODO: Props?
142+
var props = bldr.get_Properties(0);
143+
// TODO: *** check?
144+
145+
bldr.Append(" ", props);
146+
147+
// Insert paragraph number.
148+
int iPara = stText.ParagraphsOS.IndexOf(this) + 1;
149+
bldr.Replace(bldr.Length, bldr.Length, iPara.ToString(), props);
150+
151+
// And a period...
152+
bldr.Replace(bldr.Length, bldr.Length, ".", props);
153+
154+
// And now the segment number
155+
int iseg = SegmentsOS.IndexOf(seg) + 1;
156+
bldr.Replace(bldr.Length, bldr.Length, iseg.ToString(), props);
157+
return bldr.GetString();
158+
}
159+
160+
/// <summary>Pads the given int with zeroes to the max length of an int</summary>
161+
protected internal static string ZeroPadForStringComparison(int i)
162+
{
163+
// because int.MaxValue.ToString().Length is 10
164+
return i.ToString("D10");
165+
}
166+
120167
/// ------------------------------------------------------------------------------------
121168
/// <summary>
122169
/// Finds the ORC of the specified picture and deletes it from the paragraph and any

src/SIL.LCModel/InterfaceAdditions.cs

+16-6
Original file line numberDiff line numberDiff line change
@@ -3136,15 +3136,25 @@ IStTxtPara PreviousParagraph
31363136
List<IConstChartWordGroup> GetChartCellRefs();
31373137

31383138
/// ------------------------------------------------------------------------------------
3139-
/// <summary>
3140-
/// Return a Reference (e.g., Scripture reference, or text abbreviation/para #/sentence#) for the specified character
3141-
/// position (in the whole paragraph), which is assumed to belong to the specified segment.
3142-
/// (For now, ich is not actually used, but it may become important if we decide not to split segements for
3143-
/// verse numbers.)
3144-
/// </summary>
3139+
/// <summary>
3140+
/// Return a Reference (e.g., Scripture reference, or text abbreviation+para #+sentence #) for the specified character
3141+
/// position (in the whole paragraph), which is assumed to belong to the specified segment.
3142+
/// (For now, ich is not actually used, but it may become important if we decide not to split segments for
3143+
/// verse numbers.)
3144+
/// </summary>
31453145
/// ------------------------------------------------------------------------------------
31463146
ITsString Reference(ISegment seg, int ich);
31473147

3148+
/// ------------------------------------------------------------------------------------
3149+
/// <summary>
3150+
/// Return a Reference (e.g., Scripture reference, or text abbreviation+para #+sentence #) for the specified character
3151+
/// position (in the whole paragraph), which is assumed to belong to the specified segment.
3152+
/// To allow greater accuracy and precision in sorting, numbers are zero-padded to the length of <see cref="int.MaxValue"/> and ich
3153+
/// is included at the end.
3154+
/// </summary>
3155+
/// ------------------------------------------------------------------------------------
3156+
ITsString ReferenceForSorting(ISegment seg, int ich);
3157+
31483158
/// ------------------------------------------------------------------------------------
31493159
/// <summary>
31503160
/// Splits the paragraph at the specified character index.

tests/SIL.LCModel.Tests/DomainImpl/ScrTxtParaTests.cs

+32
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,38 @@ public void Reference()
567567
// segments in the previous section.
568568
Assert.That(para3.Reference(v2seg4, v2seg4.BeginOffset + 1).Text, Is.EqualTo("MAT 1:2"));
569569
}
570+
571+
/// <summary>
572+
/// Test the ReferenceForSorting method for Scripture paragraphs.
573+
/// </summary>
574+
[Test]
575+
public void ReferenceForSorting()
576+
{
577+
AddDataToMatthew();
578+
var para1 = (IStTxtPara) m_book.SectionsOS[1].ContentOA.ParagraphsOS[0]; // Actually ScrTxtPara
579+
var seg = para1.SegmentsOS[1]; // first content ref, after the chapter and verse number stuff.
580+
Assert.That(para1.ReferenceForSorting(seg, seg.BeginOffset + 1).Text, Is.EqualTo("41_MAT 0000000001:0000000001"));
581+
AddRunToMockedPara(para1, "Verse two second sentence.", null);
582+
var v2seg1 = para1.SegmentsOS[3]; // first segment of two-sentence verse
583+
Assert.That(para1.ReferenceForSorting(v2seg1, v2seg1.BeginOffset + 1).Text, Is.EqualTo("41_MAT 0000000001:0000000002a"));
584+
var v2seg2 = para1.SegmentsOS[4]; // first segment of two-sentence verse
585+
Assert.That(para1.ReferenceForSorting(v2seg2, v2seg2.BeginOffset + 1).Text, Is.EqualTo("41_MAT 0000000001:0000000002b"));
586+
IStTxtPara para2 = AddParaToMockedSectionContent((IScrSection)para1.Owner.Owner, ScrStyleNames.NormalParagraph);
587+
AddRunToMockedPara(para2, "Verse 2 seg 3", null);
588+
var v2seg3 = para2.SegmentsOS[0]; // third segment of three-sentence verse split over two paragraphs.
589+
Assert.That(para2.ReferenceForSorting(v2seg3, v2seg3.BeginOffset + 1).Text, Is.EqualTo("41_MAT 0000000001:0000000002c"));
590+
var newSection = AddSectionToMockedBook(m_book);
591+
IStTxtPara para3 = AddParaToMockedSectionContent(newSection, ScrStyleNames.NormalParagraph);
592+
AddRunToMockedPara(para3, "Verse 2 seg 4", null);
593+
var v2seg4 = para3.SegmentsOS[0]; // fourth segment of four-sentence verse split over two sections(!).
594+
// JohnT: arguably this should give 41_MAT 0000000001:0000000002d. The current implementation does not detect the
595+
// segments in the previous section.
596+
Assert.That(para3.ReferenceForSorting(v2seg4, v2seg4.BeginOffset + 1).Text, Is.EqualTo("41_MAT 0000000001:0000000002"));
597+
598+
var scrBook1Samuel = CreateBookData(9, "1 Samuel");
599+
var scrBookSusanna = CreateBookData(76, "Susanna");
600+
// TODO (Hasso) 2022.03: Enoch or some other >100 book
601+
}
570602
#endregion
571603

572604
#region Moving paragraphs between books tests

tests/SIL.LCModel.Tests/DomainImpl/StTxtParaTests.cs

+27
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,33 @@ protected override void CreateTestData()
3535
}
3636
#endregion
3737

38+
#region ReferenceForSorting method tests
39+
[Test]
40+
public void ReferenceForSorting()
41+
{
42+
var para1 = AddParaToMockedText(m_stText, null);
43+
AddRunToMockedPara(para1, "This text is indexed. It is also segmented.", null);
44+
45+
var para2 = AddParaToMockedText(m_stText, null);
46+
AddRunToMockedPara(para2, "This is the second paragraph. It is runny. It has three sentences.", null);
47+
48+
// SUT
49+
var result = para1.ReferenceForSorting(para1.SegmentsOS[0], 10);
50+
Assert.That(result, Is.EqualTo("My Interlinear Text 0000000001.0000000001 0000000010"));
51+
result = para1.ReferenceForSorting(para1.SegmentsOS[1], 25);
52+
Assert.That(result, Is.EqualTo("My Interlinear Text 0000000001.0000000002 0000000025"));
53+
result = para1.ReferenceForSorting(para2.SegmentsOS[0], 5);
54+
Assert.That(result, Is.EqualTo("My Interlinear Text 0000000002.0000000001 0000000005"));
55+
}
56+
57+
[TestCase(0, ExpectedResult = "0000000000")]
58+
[TestCase(1, ExpectedResult = "0000000001")]
59+
[TestCase(12, ExpectedResult = "0000000012")]
60+
[TestCase(512, ExpectedResult = "0000000512")]
61+
[TestCase(int.MaxValue, ExpectedResult = "2147483647")]
62+
public string ZeroPadForStringComparison(int i) => StTxtPara.ZeroPadForStringComparison(i);
63+
#endregion ReferenceForSorting method tests
64+
3865
#region ReplaceTextRange method tests
3966
///--------------------------------------------------------------------------------------
4067
/// <summary>

0 commit comments

Comments
 (0)