Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix LT-21870 and LT-21872 and boundary markers #311

Merged
merged 4 commits into from
Aug 26, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ artifacts/
lib/downloads/
.idea/
.vs/
*.bak

src/SIL.LCModel.Core/KernelInterfaces/Kernel.cs
src/SIL.LCModel/Infrastructure/Impl/Generated*.cs
Expand Down
17 changes: 16 additions & 1 deletion src/SIL.LCModel/Application/ApplicationServices/XmlImportData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -995,6 +995,18 @@ private void ReadXmlObject(XmlReader xrdr, FieldInfo fi, ICmObject objToUse)
cmo = m_cache.LangProject.LexDbOA;
Debug.Assert(cmo != null);
break;
case "PhBdryMarker":
IPhBdryMarkerRepository repository = m_cache.ServiceLocator.GetInstance<IPhBdryMarkerRepository>();
IPhBdryMarkerFactory factory = m_cache.ServiceLocator.GetInstance<IPhBdryMarkerFactory>();
Guid guid = Guid.Parse(xrdr.GetAttribute("Guid"));
IPhBdryMarker marker;
if (repository.TryGetObject(guid, out marker))
cmo = marker;
else
cmo = factory.Create(guid, (IPhPhonemeSet)fi.Owner);
// Remove the default code added by PhTerminalUnit.SetDefaultValuesAfterInit in OverridesLing_Lex.
(cmo as PhBdryMarker).CodesOS.Clear();
break;
case "PhPhonData":
cmo = m_cache.LangProject.PhonologicalDataOA;
Debug.Assert(cmo != null);
Expand All @@ -1003,6 +1015,10 @@ private void ReadXmlObject(XmlReader xrdr, FieldInfo fi, ICmObject objToUse)
cmo = m_cache.LangProject.PhFeatureSystemOA;
Debug.Assert(cmo != null);
break;
case "PhPhonemeSet":
cmo = m_cache.LangProject.PhonologicalDataOA.GetPhonemeSet();
Debug.Assert(cmo != null);
break;
default:
int clid = m_mdc.GetClassId(sClass);
if (fi != null)
Expand Down Expand Up @@ -1048,7 +1064,6 @@ private void ReadXmlObject(XmlReader xrdr, FieldInfo fi, ICmObject objToUse)
cmo = m_repoCmObject.GetObject(hvo);
// Remove the default code added by PhTerminalUnit.SetDefaultValuesAfterInit in OverridesLing_Lex.
(cmo as PhPhoneme)?.CodesOS.Clear();
(cmo as PhBdryMarker)?.CodesOS.Clear();
// Remove default values.
(cmo as PhRegularRule)?.RightHandSidesOS.Clear();
}
Expand Down
15 changes: 15 additions & 0 deletions src/SIL.LCModel/DomainImpl/OverridesLing_Lex.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6858,6 +6858,21 @@ public List<string> AllPhonemes()
return phReps;
}

/// <summary>
/// Get the PhonemeSet.
/// Hides the fact that multiple PhonemeSets used to be allowed.
/// </summary>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public IPhPhonemeSet GetPhonemeSet()
{
if (this.PhonemeSetsOS.Count == 0)
throw new Exception("Missing PhonemeSet.");
if (this.PhonemeSetsOS.Count > 1)
throw new Exception("Too many PhonemeSets.");
return this.PhonemeSetsOS[0];
}

/// <summary>
/// Return the list of abbreviations for all the natural classes defined, each in the
/// default analysis writing system.
Expand Down
16 changes: 10 additions & 6 deletions src/SIL.LCModel/DomainServices/M3ModelExportServices.cs
Original file line number Diff line number Diff line change
Expand Up @@ -591,12 +591,16 @@ select ExportItemAsReference(constraint, constraints.IndexOf(constraint), "Featu
new XAttribute("Id", rhs.Hvo),
new XElement("StrucChange", from structChange in rhs.StrucChangeOS
select ExportContext(structChange)),
new XElement("InputPOSes", from pos in rhs.InputPOSesRC
select ExportItemAsReference(pos, "RequiredPOS")),
new XElement("ReqRuleFeats", from rrf in rhs.ReqRuleFeatsRC
select ExportItemAsReference(rrf, "RuleFeat")),
new XElement("ExclRuleFeats", from erf in rhs.ExclRuleFeatsRC
select ExportItemAsReference(erf, "RuleFeat")),
// RuleFeats and POS are not part of the phonology.
phonology ? null
: new XElement("InputPOSes", from pos in rhs.InputPOSesRC
select ExportItemAsReference(pos, "RequiredPOS")),
phonology ? null
: new XElement("ReqRuleFeats", from rrf in rhs.ReqRuleFeatsRC
select ExportItemAsReference(rrf, "RuleFeat")),
phonology ? null
: new XElement("ExclRuleFeats", from erf in rhs.ExclRuleFeatsRC
select ExportItemAsReference(erf, "RuleFeat")),
new XElement("LeftContext", ExportContext(rhs.LeftContextOA)),
new XElement("RightContext", ExportContext(rhs.RightContextOA)))));
break;
Expand Down
54 changes: 20 additions & 34 deletions src/SIL.LCModel/DomainServices/PhonologyServices.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
using SIL.LCModel.Core.Text;
using SIL.LCModel.Infrastructure.Impl;
using static Icu.Normalization.Normalizer2;
using SIL.LCModel.Core.KernelInterfaces;

namespace SIL.LCModel.DomainServices
{
Expand Down Expand Up @@ -74,42 +75,27 @@ public void ImportPhonologyFromXml(TextReader rdr)
// () => AssignVernacularWritingSystemToDefaultPhPhonemes(Cache));
}

private void AssignVernacularWritingSystemToDefaultPhPhonemes(LcmCache cache)
/// <summary>
/// Clear PhonologicalData and Phonological Features.
/// Don't clear boundary markers.
/// </summary>
public void DeletePhonology()
{
// For all PhCodes in the default phoneme set, change the writing system from "en" to icuLocale
if (cache.LanguageProject.PhonologicalDataOA.PhonemeSetsOS.Count == 0)
return;
var phSet = cache.LanguageProject.PhonologicalDataOA.PhonemeSetsOS[0];
int wsVern = m_wsVernId == null
? cache.DefaultVernWs
: cache.ServiceLocator.WritingSystemManager.Get(m_wsVernId).Handle;
foreach (var phone in phSet.PhonemesOC)
{
foreach (var code in phone.CodesOS)
{

if (code.Representation.VernacularDefaultWritingSystem.Length == 0)
code.Representation.VernacularDefaultWritingSystem =
TsStringUtils.MakeString(code.Representation.UserDefaultWritingSystem.Text, wsVern);
}
if (phone.Name.VernacularDefaultWritingSystem.Length == 0)
phone.Name.VernacularDefaultWritingSystem =
TsStringUtils.MakeString(phone.Name.UserDefaultWritingSystem.Text, wsVern);
}
foreach (var mrkr in phSet.BoundaryMarkersOC)
NonUndoableUnitOfWorkHelper.Do(Cache.ServiceLocator.GetInstance<IActionHandler>(), () =>
{
foreach (var code in mrkr.CodesOS)
{
if (code.Representation.VernacularDefaultWritingSystem.Length == 0)
code.Representation.VernacularDefaultWritingSystem =
TsStringUtils.MakeString(code.Representation.UserDefaultWritingSystem.Text, wsVern);
}
if (mrkr.Name.VernacularDefaultWritingSystem.Length == 0)
mrkr.Name.VernacularDefaultWritingSystem =
TsStringUtils.MakeString(mrkr.Name.UserDefaultWritingSystem.Text, wsVern);
}
IPhPhonData phonData = Cache.LangProject.PhonologicalDataOA;
// Delete what is covered by ImportPhonology.
phonData.ContextsOS.Clear();
phonData.EnvironmentsOS.Clear();
phonData.FeatConstraintsOS.Clear();
phonData.NaturalClassesOS.Clear();
phonData.GetPhonemeSet().PhonemesOC.Clear();
// Don't clear phonData.GetPhonemeSet().BoundaryMarkersOC!
// They have GUIDs known to the code.
phonData.PhonRulesOS.Clear();
Cache.LanguageProject.PhFeatureSystemOA.TypesOC.Clear();
Cache.LanguageProject.PhFeatureSystemOA.FeaturesOC.Clear();
});
}


}
}
6 changes: 6 additions & 0 deletions src/SIL.LCModel/InterfaceAdditions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5626,6 +5626,12 @@ public partial interface IPhPhonData
/// </summary>
List<string> AllNaturalClassAbbrs();

/// <summary>
/// Get the PhonemeSet.
/// Hides the fact that the data structure used to allow more than one.
/// </summary>
IPhPhonemeSet GetPhonemeSet();

/// <summary>
/// Rebuild the list of PhonRuleFeats
/// </summary>
Expand Down
34 changes: 34 additions & 0 deletions tests/SIL.LCModel.Tests/DomainServices/PhonologyServicesTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,15 @@ private void TestProject(string projectsDirectory, string dbFileName)
using (var cache = LcmCache.CreateCacheFromExistingData(projectId, "en", m_ui, m_lcmDirectories, new LcmSettings(),
new DummyProgressDlg()))
{
// Create PhonemeSet if necessary.
NonUndoableUnitOfWorkHelper.Do(m_cache.ActionHandlerAccessor, () =>
{
if (m_cache.LangProject.PhonologicalDataOA.PhonemeSetsOS.Count == 0)
{
var phonemeset = m_cache.ServiceLocator.GetInstance<IPhPhonemeSetFactory>().Create();
m_cache.LangProject.PhonologicalDataOA.PhonemeSetsOS.Add(phonemeset);
}
});
// Export project as XML.
var services = new PhonologyServices(cache);
XDocument xdoc = services.ExportPhonologyAsXml();
Expand All @@ -109,6 +118,7 @@ private void TestProject(string projectsDirectory, string dbFileName)
var vernWs = cache.ServiceLocator.WritingSystemManager.Get(cache.DefaultVernWs);
SetDefaultVernacularWritingSystem(m_cache, vernWs);
var services2 = new PhonologyServices(m_cache, vernWs.Id);
services2.DeletePhonology();
services2.ImportPhonologyFromXml(rdr);
xdoc2 = services2.ExportPhonologyAsXml();
}
Expand All @@ -125,15 +135,39 @@ private void TestXml(string xml, string vernWs)
{
m_cache.ServiceLocator.WritingSystems.DefaultVernacularWritingSystem =
m_cache.ServiceLocator.WritingSystemManager.Get(vernWs);
if (m_cache.LangProject.PhonologicalDataOA.PhonemeSetsOS.Count == 0)
{
var phonemeset = m_cache.ServiceLocator.GetInstance<IPhPhonemeSetFactory>().Create();
m_cache.LangProject.PhonologicalDataOA.PhonemeSetsOS.Add(phonemeset);
}
});
ILcmOwningSequence<IPhPhonemeSet> phonemeList = m_cache.LangProject.PhonologicalDataOA.PhonemeSetsOS;
IPhPhonemeSet phonemeSet = m_cache.LangProject.PhonologicalDataOA.GetPhonemeSet();
var services = new PhonologyServices(m_cache);
services.DeletePhonology();
using (var rdr = new StringReader(xml))
{
services.ImportPhonologyFromXml(rdr);
var xdoc2 = services.ExportPhonologyAsXml();
var xml2 = xdoc2.ToString();
TestXml(xdoc, xdoc2);
}
// Verify that the references to the PhonemeSet didn't change.
Assert.IsTrue(ReferenceEquals(phonemeList, m_cache.LangProject.PhonologicalDataOA.PhonemeSetsOS));
Assert.IsTrue(ReferenceEquals(phonemeSet, m_cache.LangProject.PhonologicalDataOA.GetPhonemeSet()));
// Verify that the boundary markers exist with the right GUIDs.
bool hasMorphBdry = false;
bool hasWordBdry = false;
foreach (var marker in m_cache.LangProject.PhonologicalDataOA.GetPhonemeSet().BoundaryMarkersOC)
{
if (marker.Guid == LangProjectTags.kguidPhRuleMorphBdry)
hasMorphBdry = true;
if (marker.Guid == LangProjectTags.kguidPhRuleWordBdry)
hasWordBdry = true;
}
Assert.IsTrue(hasMorphBdry);
Assert.IsTrue(hasWordBdry);
Assert.IsTrue(m_cache.LangProject.PhonologicalDataOA.GetPhonemeSet().BoundaryMarkersOC.Count == 2);
}

private void TestXml(XDocument xdoc, XDocument xdoc2)
Expand Down
Loading