// STEP 1: Add missing terms, and move existing terms to the correct // place in the tree, and possibly introducing temporary names // to avoid sibling conflicts. static void ProcessAddsAndMoves(TermSetItem parentItem, ItemGoal parentItemGoal, Dictionary <Guid, Term> termsById) { foreach (TermGoal termGoal in parentItemGoal.TermGoals) { // Does the term already exist? Term term; if (termsById.TryGetValue(termGoal.Id, out term)) { // The term exists, so ensure that it is a child of parentItem. Guid termParentId = (term.Parent != null) ? term.Parent.Id : term.TermSet.Id; if (termParentId != parentItem.Id) { MoveToParentItem(term, parentItem); } else { Log("Verified position of term \"" + term.Name + "\""); } } else { Log("* Creating missing term \"" + termGoal.Name + "\""); string safeName = GenerateNameWithoutSiblingConflicts(parentItem, termGoal.Name); term = parentItem.CreateTerm(safeName, lcid, termGoal.Id); parentItem.TermStore.CommitAll(); termsById.Add(term.Id, term); } ProcessAddsAndMoves(term, termGoal, termsById); // recurse } }
// STEP 3: Update the term properties, including correcting any // temporary names that were introduced in step 1. static void ProcessPropertyUpdates(TermSetItem parentItem, ItemGoal parentItemGoal) { foreach (Term term in parentItem.Terms) { TermGoal termGoal = parentItemGoal.TermGoals.FirstOrDefault(t => t.Id == term.Id); if (termGoal == null) { continue; // This is a term that would have been deleted by the ProcessDeletes() method. } // ----------------- string goalName = TaxonomyItem.NormalizeName(termGoal.Name); if (term.Name != goalName) { Log("* Renaming term from \"" + term.Name + "\" to \"" + termGoal.Name + "\""); term.Name = goalName; } HashSet <string> labels = new HashSet <string>( term.Labels.Where(l => !l.IsDefaultForLanguage).Select(l => l.Value)); HashSet <string> labelsGoal = new HashSet <string>(termGoal.OtherLabels); // Delete any extra labels. foreach (string label in labels.Except(labelsGoal)) { Log("* Term \"" + term.Name + "\": Deleting label \"" + label + "\""); term.Labels.First(l => l.Value == label).Delete(); } // Add any missing labels. foreach (string label in labelsGoal.Except(labels)) { Log("* Term \"" + term.Name + "\": Adding label \"" + label + "\""); term.CreateLabel(label, lcid, isDefault: false); } if (term.GetDescription() != termGoal.Description) { Log("* Term \"" + term.Name + "\": Updating description"); term.SetDescription(termGoal.Description, lcid); } if (term.IsDeprecated != termGoal.IsDeprecated) { Log("* Term \"" + term.Name + "\": Marking as " + (termGoal.IsDeprecated ? "Deprecated" : "Not deprecated")); term.Deprecate(termGoal.IsDeprecated); } // ----------------- ProcessPropertyUpdates(term, termGoal); // Recurse. } }
// STEP 3: Update the term properties, including correcting any // temporary names that were introduced in step 1. static void ProcessPropertyUpdates(Wrapper parentWrapper, ItemGoal parentItemGoal) { foreach (Wrapper wrapper in parentWrapper.ChildTerms) { // Find the corresponding TermGoal object. TermGoal termGoal = parentItemGoal.TermGoals.First(t => t.Id == wrapper.Id); Term term = (Term)wrapper.Item; // ----------------- if (term.Name != termGoal.Name) { // Consider the TaxonomyItem.NormalizeName() method. Log("* Renaming term from \"" + term.Name + "\" to \"" + termGoal.Name + "\""); term.Name = termGoal.Name; } HashSet <string> labels = new HashSet <string>( term.Labels.ToList().Where(l => !l.IsDefaultForLanguage).Select(l => l.Value)); HashSet <string> labelsGoal = new HashSet <string>(termGoal.OtherLabels); // Delete any extra labels. foreach (string label in labels.Except(labelsGoal)) { Log("* Term \"" + term.Name + "\": Deleting label \"" + label + "\""); term.Labels.ToList().First(l => l.Value == label).DeleteObject(); } // Add any missing labels. foreach (string label in labelsGoal.Except(labels)) { Log("* Term \"" + term.Name + "\": Adding label \"" + label + "\""); term.CreateLabel(label, Program.lcid, isDefault: false); } if (wrapper.TermDescription.Value != termGoal.Description) { Log("* Term \"" + term.Name + "\": Updating description"); term.SetDescription(termGoal.Description, Program.lcid); } if (term.IsDeprecated != termGoal.IsDeprecated) { Log("* Term \"" + term.Name + "\": Marking as " + (termGoal.IsDeprecated ? "Deprecated" : "Not deprecated")); term.Deprecate(termGoal.IsDeprecated); } // ----------------- ProcessPropertyUpdates(wrapper, termGoal); // recurse } }
// STEP 1: Add missing terms, and move existing terms to the correct // place in the tree. Possibly introduce temporary names to avoid // sibling conflicts. static void ProcessAddsAndMoves(Wrapper parentWrapper, ItemGoal parentItemGoal) { Debug.Assert(parentWrapper.Id == parentItemGoal.Id); foreach (TermGoal termGoal in parentItemGoal.TermGoals) { // Does the term already exist? Wrapper wrapper; if (!Program.itemsById.TryGetValue(termGoal.Id, out wrapper)) { Log("* Creating missing term \"" + termGoal.Name + "\""); string safeName = GenerateNameWithoutSiblingConflicts(parentWrapper, termGoal.Name); Term newTerm = parentWrapper.Item.CreateTerm(safeName, Program.lcid, termGoal.Id); wrapper = new Wrapper(newTerm, termGoal.Id, parentWrapper.Id, safeName); AddWrapperToTree(wrapper); Program.clientContext.Load(newTerm, Program.termRetrievals); } else { // The term exists, so ensure that it is a child of parentItem. if (wrapper.ParentId == parentWrapper.Id) { Log("Verified position of term \"" + wrapper.Name + "\""); } else { Log("* Moving Term \"" + wrapper.Name + "\" to be a child of \"" + parentWrapper.Name + "\""); // Avoid key violations introduced by the move. string safeName = GenerateNameWithoutSiblingConflicts(parentWrapper, termGoal.Name); if (wrapper.Item.Name != safeName) { wrapper.Item.Name = safeName; } ((Term)wrapper.Item).Move(parentWrapper.Item); // Update the data structure. Wrapper oldParent = Program.itemsById[wrapper.ParentId]; oldParent.ChildTerms.Remove(wrapper); wrapper.ParentId = parentWrapper.Id; parentWrapper.ChildTerms.Add(wrapper); } } ProcessAddsAndMoves(wrapper, termGoal); // Recurse. } }
// STEP 2: Delete any leftover terms. static void ProcessDeletes(Wrapper parentWrapper, ItemGoal parentItemGoal) { foreach (Wrapper wrapper in parentWrapper.ChildTerms.ToList()) { TermGoal termGoal = parentItemGoal.TermGoals.FirstOrDefault(t => t.Id == wrapper.Id); if (termGoal == null) { Log("* Deleting extra term \"" + wrapper.Name + "\""); wrapper.Item.DeleteObject(); parentWrapper.ChildTerms.Remove(wrapper); } else { ProcessDeletes(wrapper, termGoal); // Recurse. } } }
// STEP 2: Delete any leftover terms. static void ProcessDeletes(TermSetItem parentItem, ItemGoal parentItemGoal) { foreach (Term term in parentItem.Terms) { TermGoal termGoal = parentItemGoal.TermGoals.FirstOrDefault(t => t.Id == term.Id); if (termGoal == null) { Log("* Deleting extra term \"" + term.Name + "\""); term.Delete(); term.TermStore.CommitAll(); } else { ProcessDeletes(term, termGoal); // recurse } } }