diff --git a/src/SIL.LCModel/DomainImpl/OverridesLing_MoClasses.cs b/src/SIL.LCModel/DomainImpl/OverridesLing_MoClasses.cs index ea6eb2fe..b9cf612c 100644 --- a/src/SIL.LCModel/DomainImpl/OverridesLing_MoClasses.cs +++ b/src/SIL.LCModel/DomainImpl/OverridesLing_MoClasses.cs @@ -2731,6 +2731,26 @@ public void SetCloneProperties(ICmObject clone) { template.StratumRA = StratumRA; } + MakeTemplateNameUnique(template); + } + + internal void MakeTemplateNameUnique(IMoInflAffixTemplate newTemplate) + { + // Get existing names. + ISet names = new HashSet(); + IEnumerable templates = Services.ObjectRepository.AllInstances(newTemplate.ClassID); + foreach (IMoInflAffixTemplate template in templates) + { + if (template == newTemplate) + continue; + for (int i = 0; i < template.Name.StringCount; i++) + { + ITsString tss = template.Name.GetStringFromIndex(i, out _); + names.Add(tss.Text); + } + } + // Make newSlot name unique. + MoInflAffixSlot.MakeNameUnique(newTemplate.Name, names); } #endregion } @@ -2882,6 +2902,105 @@ public int CompareTo(object obj) } #endregion + + #region ICloneableCmObject Members + /// ------------------------------------------------------------------------------------ + /// + /// Clones this instance. + /// + /// Destination object for clone operation + /// ------------------------------------------------------------------------------------ + public void SetCloneProperties(ICmObject clone) + { + IMoInflAffixSlot slot = clone as IMoInflAffixSlot; + if (slot == null) + throw new ApplicationException("Failed to copy inflectional affix slot: the target is not an inflectional affix slote."); + + slot.Name.CopyAlternatives(Name); + slot.Description.CopyAlternatives(Description); + slot.Optional = Optional; + // Make copies of Affixes. + foreach (IMoInflAffMsa msa in Affixes) + { + if (msa.Owner is not ILexEntry entry) + // Shouldn't happen, but just in case... + continue; + foreach (ILexSense sense in entry.SensesOS.ToList()) { + CopySensesWithMSA(entry, sense, msa, slot); + } + } + MakeSlotNameUnique(slot); + } + + /// + /// Copy sense with new slot if it's MorphoSyntaxAnalysisRA equals msa. + /// Recurse on the subsenses. + /// + internal void CopySensesWithMSA(ILexEntry entry, ILexSense sense, IMoInflAffMsa msa, IMoInflAffixSlot newSlot) + { + // Recurse on subsense first. + foreach (ILexSense subsense in sense.SensesOS.ToList()) + { + CopySensesWithMSA(entry, subsense, msa, newSlot); + } + if (sense.MorphoSyntaxAnalysisRA == msa) + { + // Create a new sense. + SandboxGenericMSA sandboxMsa = SandboxGenericMSA.Create(msa); + sandboxMsa.Slot = newSlot; + ILexSense newSense = Services.GetInstance().Create(entry, sandboxMsa, sense.Gloss.BestAnalysisAlternative); + newSense.Gloss.MergeAlternatives(sense.Gloss); + } + } + + internal void MakeSlotNameUnique(IMoInflAffixSlot newSlot) + { + // Get existing names. + ISet names = new HashSet(); + IEnumerable slots = Services.ObjectRepository.AllInstances(newSlot.ClassID); + foreach (IMoInflAffixSlot slot in slots) + { + if (slot == newSlot) + continue; + for (int i = 0; i < slot.Name.StringCount; i++) + { + ITsString tss = slot.Name.GetStringFromIndex(i, out _); + names.Add(tss.Text); + } + } + // Make newSlot name unique. + MakeNameUnique(newSlot.Name, names); + } + + static internal void MakeNameUnique(IMultiUnicode name, ISet names) + { + for (int i = 0; i < name.StringCount; i++) + { + int ws; + ITsString tss = name.GetStringFromIndex(i, out ws); + string text = tss.Text; + // Get existing id. + int id = 1; + int idStart = text.Length; + while (idStart > 0 && Char.IsNumber(text[idStart - 1])) + idStart = idStart - 1; + if (idStart < text.Length) + id = Int32.Parse(text.Substring(idStart)); + // Look for a unique name. + while (true) + { + id += 1; + string newName = text.Substring(0, idStart) + id.ToString(); + if (!names.Contains(newName)) + { + // Replace name[i] with unique name. + name.set_String(ws, newName); + break; + } + } + } + } + #endregion } /// diff --git a/src/SIL.LCModel/InterfaceAdditions.cs b/src/SIL.LCModel/InterfaceAdditions.cs index 81d40bc6..73f5835e 100644 --- a/src/SIL.LCModel/InterfaceAdditions.cs +++ b/src/SIL.LCModel/InterfaceAdditions.cs @@ -2097,7 +2097,7 @@ public partial interface IMoInflAffixTemplate : ICloneableCmObject } /// - public partial interface IMoInflAffixSlot + public partial interface IMoInflAffixSlot : ICloneableCmObject { /// IEnumerable Affixes { get; }