Beispiel #1
0
 public static LocalTerm CreateTermLinkUsingId(LocalTerm sourceTerm, bool isPinnedRoot = false)
 {
     if (!sourceTerm.IsSourceTerm)
     {
         throw new InvalidOperationException("Cannot create a link to a term with IsSourceTerm=false");
     }
     return(LocalTerm.CreateTermLinkUsingId(sourceTerm.Id, sourceTerm.DefaultLanguageLcid, sourceTerm.Name, isPinnedRoot));
 }
Beispiel #2
0
        /// <summary>
        /// Returns the concatenated names of this term's parents, followed by this term.
        /// For example, if A has child term B, which has child term C, then the path is "A;B;C".
        /// </summary>
        public string GetPath()
        {
            LocalTerm parentTerm = this.ParentItem as LocalTerm;

            if (parentTerm == null)
            {
                return(this.Name);
            }
            return(parentTerm.GetPath() + ";" + this.Name);
        }
Beispiel #3
0
        private LocalTerm(int defaultLanguageLcid, string termLinkSourcePath, bool isPinnedRoot)
            : base(Guid.Empty, defaultLanguageLcid)
        {
            ToolkitUtilities.ConfirmNotNull(termLinkSourcePath, "termLinkSourcePath");
            this.sharedDataIfSourceTerm = null;
            this.termLinkData           = new TermLinkData();
            this.termLinkData.TermLinkSourcePathParts = LocalTerm.ParseTermLinkSourcePath(termLinkSourcePath);

            Debug.Assert(this.TermKind == LocalTermKind.TermLinkUsingPath);
        }
Beispiel #4
0
        private SharedData GetSharedDataFromSourceTerm(bool exceptionIfMissing)
        {
            LocalTerm sourceTerm = this.SourceTerm;

            if (sourceTerm == null)
            {
                if (exceptionIfMissing)
                {
                    throw new InvalidOperationException(
                              "This operation cannot be performed because the source term is not part of the tree");
                }
                return(null);
            }

            Debug.Assert(sourceTerm.sharedDataIfSourceTerm != null);
            return(sourceTerm.sharedDataIfSourceTerm);
        }
Beispiel #5
0
        private void AddSubtreeToTable(LocalTaxonomyItem rootItem)
        {
            foreach (LocalTaxonomyItem localItem in ToolkitUtilities.GetPreorder(rootItem,
                                                                                 (LocalTaxonomyItem x) => x.ChildItems))
            {
                LocalTerm localTerm = localItem as LocalTerm;
                if (localTerm != null && localItem.Id != Guid.Empty)
                {
                    // Add localTerm to the table
                    List <LocalTerm> termList = null;
                    if (!this.termsByGuid.TryGetValue(localTerm.Id, out termList))
                    {
                        // Create the missing list
                        termList = new List <LocalTerm>();
                        this.termsByGuid.Add(localTerm.Id, termList);
                    }

                    // Add the localTerm to the list
                    if (localTerm.IsSourceTerm)
                    {
                        for (int i = 0; i < termList.Count; ++i)
                        {
                            if (termList[i].IsSourceTerm)
                            {
                                throw new InvalidOperationException(string.Format(
                                                                        "The term \"{0}\" cannot be the source term in two different term sets (TermId={1})",
                                                                        localTerm.Name, localTerm.Id));
                            }
                        }
                        // Source term is first in the list
                        termList.Insert(0, localTerm);
                    }
                    else
                    {
                        termList.Add(localTerm);
                    }
                }
            }
        }
Beispiel #6
0
        /// <summary>
        /// Compares otherTerm's labels with this term's labels to see if there are any conflicts.
        /// A conflict occurs if the default labels (i.e. term names) are equal for a given language LCID.
        /// Note that we compare all LCIDs from both terms; if a term does not have a default label
        /// for a given LCID, then we fallback to the default language.  (Recall that the "term name"
        /// is the "default label" for each language, and there is also a "default language" for
        /// the term store.)
        ///
        /// This check can also consider a proposedNewLabelForOtherTerm, which allows us to detect
        /// problems that would be introduced by adding/changing the otherTerm, before the change
        /// is performed.
        /// </summary>
        /// <returns>
        /// An "objection" (i.e. error message) if there is a conflict, or null otheriwse.
        /// </returns>
        internal string ExplainHasLabelConflictWith(LocalTerm otherTerm, LocalTermLabel proposedNewLabelForOtherTerm = null)
        {
            Debug.Assert(this.TermKind == LocalTermKind.NormalTerm);
            Debug.Assert(otherTerm.TermKind == LocalTermKind.NormalTerm);

            // The proposedNewLabelForOtherTerm only affects this comparison if it is the default label for a language
            // (i.e. we don't care about synonyms)
            if (proposedNewLabelForOtherTerm != null && !proposedNewLabelForOtherTerm.IsDefault)
            {
                proposedNewLabelForOtherTerm = null;
            }

            SharedData thisSharedData  = this.GetSharedDataFromSourceTerm(exceptionIfMissing: true);
            SharedData otherSharedData = otherTerm.GetSharedDataFromSourceTerm(exceptionIfMissing: true);

            foreach (int lcid in
                     // Take the union of the LCIDs from both terms, sorted in increasing order,
                     // but compare the default language first
                     new[] { this.DefaultLanguageLcid }
                     .Union(
                         thisSharedData.LabelsByLcid.Keys
                         .Union(otherSharedData.LabelsByLcid.Keys)
                         .Where(x => x != this.DefaultLanguageLcid)
                         .OrderBy(x => x)
                         .Distinct()
                         ))
            {
                string thisName  = this.GetNameWithDefault(lcid);
                string otherName = otherTerm.GetNameWithDefaultForConflict(otherSharedData, lcid, proposedNewLabelForOtherTerm);

                if (thisName.Equals(otherName, StringComparison.OrdinalIgnoreCase))
                {
                    return("The term name \"" + otherName + "\" is already in use by a sibling term"
                           + " (LCID=" + lcid + ")");
                }
            }
            return(null);
        }
Beispiel #7
0
        private void ProcessTerm(XElement xmlNode, LocalTermContainer parentTermContainer, List <Guid> parentInOrderList,
                                 bool isTermLink)
        {
            LocalTerm term;

            Guid id = this.GetGuidAttributeValue(xmlNode, TaxmlSpec.IdToken) ?? Guid.Empty;

            if (isTermLink)
            {
                string nameHint           = this.GetAttributeValue(xmlNode, TaxmlSpec.NameHintToken) ?? "";
                string termLinkSourcePath = this.GetAttributeValue(xmlNode, TaxmlSpec.TermLinkSourcePathToken) ?? "";
                if (id == Guid.Empty && string.IsNullOrWhiteSpace(termLinkSourcePath))
                {
                    throw new ParseException(
                              "TermLink elements must have either the ID attribute or the TermLinkSourcePath attribute",
                              xmlNode);
                }

                if (termLinkSourcePath.Length > 0)
                {
                    term = LocalTerm.CreateTermLinkUsingPath(parentTermContainer.DefaultLanguageLcid, termLinkSourcePath);
                }
                else
                {
                    term = LocalTerm.CreateTermLinkUsingId(id, parentTermContainer.DefaultLanguageLcid, nameHint);
                }
            }
            else
            {
                string name = this.GetRequiredAttributeValue(xmlNode, TaxmlSpec.NameToken);
                term = LocalTerm.CreateTerm(id, name, parentTermContainer.DefaultLanguageLcid);
            }

            this.ReadTaxmlComments(xmlNode, term);

            bool?isAvailableForTagging = this.GetBooleanAttributeValue(xmlNode, TaxmlSpec.IsAvailableForTaggingToken);

            if (isAvailableForTagging.HasValue)
            {
                term.IsAvailableForTagging = isAvailableForTagging.Value;
            }

            if (isTermLink)
            {
                bool?isPinnedRoot = this.GetBooleanAttributeValue(xmlNode, TaxmlSpec.IsPinnedRootToken);
                if (isPinnedRoot.HasValue)
                {
                    term.IsPinnedRoot = isPinnedRoot.Value;
                }
            }
            else
            {
                string owner = this.GetAttributeValue(xmlNode, TaxmlSpec.OwnerToken);
                if (owner != null)
                {
                    term.Owner = owner;
                }

                bool?isDeprecated = this.GetBooleanAttributeValue(xmlNode, TaxmlSpec.IsDeprecatedToken);
                if (isDeprecated.HasValue)
                {
                    term.IsDeprecated = isDeprecated.Value;
                }
            }

            bool inOrder = this.GetBooleanAttributeValue(xmlNode, TaxmlSpec.InOrderToken) ?? false;

            if (inOrder)
            {
                if (term.Id == Guid.Empty)
                {
                    throw new ParseException("The InOrder attribute cannot be used when the term ID is empty", xmlNode);
                }
                parentInOrderList.Add(term.Id);
            }

            // Add the term set to the parent term / term set
            parentTermContainer.AddTerm(term);

            var inOrderList = new List <Guid>();

            foreach (XElement childNode in xmlNode.Elements())
            {
                switch (childNode.Name.LocalName)
                {
                case TaxmlSpec.LocalizedDescriptionToken:
                    int descriptionLcid = this.GetLcidFromLanguageAttribute(childNode, term);
                    term.SetDescription(childNode.Value, descriptionLcid);
                    break;

                case TaxmlSpec.CustomPropertyToken:
                    this.ProcessCustomProperty(term.CustomProperties, childNode);
                    break;

                case TaxmlSpec.LocalCustomPropertyToken:
                    this.ProcessCustomProperty(term.LocalCustomProperties, childNode);
                    break;

                case TaxmlSpec.CustomSortOrderToken:
                    this.ProcessCustomSortOrder(term.CustomSortOrder, childNode);
                    break;

                case TaxmlSpec.LabelToken:
                    int  labelLcid         = this.GetLcidFromLanguageAttribute(childNode, term);
                    bool?setAsDefaultLabel = this.GetBooleanAttributeValue(childNode,
                                                                           TaxmlSpec.IsDefaultForLanguageToken);
                    term.AddLabel(childNode.Value, labelLcid, setAsDefaultLabel ?? false);
                    break;

                case TaxmlSpec.TermToken:
                    this.ProcessTerm(childNode, term, inOrderList, isTermLink: false);
                    break;

                case TaxmlSpec.TermLinkToken:
                    this.ProcessTerm(childNode, term, inOrderList, isTermLink: true);
                    break;

                case TaxmlSpec.SyncActionToken:
                    this.ProcessSyncAction(childNode, term);
                    break;

                default:
                    throw new ParseException("Unimplemented XML tag \"" + childNode.Name.LocalName + "\"", childNode);
                }
            }

            this.ProcessInOrderList(term, inOrderList, xmlNode);
        }
Beispiel #8
0
 public CustomOrderedTerm(LocalTerm term, bool writeInOrderAttribute)
 {
     this.Term = term;
     this.WriteInOrderAttribute = writeInOrderAttribute;
 }
Beispiel #9
0
        private void ProcessChildTerms(XElement termContainerElement,
                                       LocalTermContainer termContainer, List <CustomOrderedTerm> orderedTerms)
        {
            LocalTermStore termStore = termContainer.GetTermStore();

            foreach (CustomOrderedTerm customOrderedTerm in orderedTerms)
            {
                LocalTerm term = customOrderedTerm.Term;

                bool isTermLink = term.TermKind != LocalTermKind.NormalTerm;

                XElement termElement;
                if (isTermLink)
                {
                    termElement = new XElement(TaxmlSpec.TermLinkToken);
                    if (term.TermKind == LocalTermKind.TermLinkUsingId &&
                        term.TermLinkNameHint.Length > 0)
                    {
                        termElement.Add(new XAttribute(TaxmlSpec.NameHintToken, term.TermLinkNameHint));
                    }
                }
                else
                {
                    termElement = new XElement(TaxmlSpec.TermToken, new XAttribute(TaxmlSpec.NameToken, term.Name));
                }

                termContainerElement.Add(termElement);
                this.ProcessTaxmlComments(termElement, term);

                if (term.Id != Guid.Empty)
                {
                    termElement.Add(new XAttribute(TaxmlSpec.IdToken, term.Id.ToString("B")));
                }

                if (customOrderedTerm.WriteInOrderAttribute)
                {
                    if (termContainer.CustomSortOrder.Contains(term.Id))
                    {
                        termElement.Add(new XAttribute(TaxmlSpec.InOrderToken, true));
                    }
                }

                if (!term.IsAvailableForTagging)
                {
                    termElement.Add(new XAttribute(TaxmlSpec.IsAvailableForTaggingToken, false));
                }

                this.ProcessSyncActionElement(term, termElement);

                if (isTermLink)
                {
                    if (!string.IsNullOrWhiteSpace(term.TermLinkSourcePath))
                    {
                        termElement.Add(new XAttribute(TaxmlSpec.TermLinkSourcePathToken, term.TermLinkSourcePath));
                    }
                    if (term.IsPinnedRoot)
                    {
                        termElement.Add(new XAttribute(TaxmlSpec.IsPinnedRootToken, true));
                    }
                }
                else
                {
                    // TODO: If the Term.Owner is the same as the parent object, can we omit it?
                    if (!string.IsNullOrEmpty(term.Owner))
                    {
                        termElement.Add(new XAttribute(TaxmlSpec.OwnerToken, term.Owner));
                    }

                    if (term.IsDeprecated)
                    {
                        termElement.Add(new XAttribute(TaxmlSpec.IsDeprecatedToken, true));
                    }

                    foreach (LocalizedString description in term.Descriptions)
                    {
                        XElement descriptionElement = new XElement(TaxmlSpec.LocalizedDescriptionToken, description);
                        termElement.Add(descriptionElement);

                        if (description.Lcid != term.DefaultLanguageLcid)
                        {
                            descriptionElement.Add(new XAttribute(TaxmlSpec.LanguageToken, description.Lcid));
                            descriptionElement.Value = description.Value;
                        }
                    }

                    this.ProcessCustomProperties(term.CustomProperties, termElement, isLocal: false);
                }

                this.ProcessCustomProperties(term.LocalCustomProperties, termElement, isLocal: true);

                List <CustomOrderedTerm> orderedChildTerms = this.ProcessCustomSortOrder(term, termElement);

                if (!isTermLink)
                {
                    foreach (LocalTermLabel label in term.Labels)
                    {
                        // If this is the Term.Name label, then it doesn't need to be specified explicitly
                        if (label.IsDefault && label.Lcid == term.DefaultLanguageLcid)
                        {
                            continue;
                        }

                        XElement labelElement = new XElement(TaxmlSpec.LabelToken, label.Value);
                        termElement.Add(labelElement);

                        if (label.Lcid != term.DefaultLanguageLcid)
                        {
                            labelElement.Add(new XAttribute(TaxmlSpec.LanguageToken, label.Lcid));
                        }

                        if (label.IsDefault)
                        {
                            labelElement.Add(new XAttribute(TaxmlSpec.IsDefaultForLanguageToken, true));
                        }
                    }
                }

                this.ProcessChildTerms(termElement, term, orderedChildTerms);
            }
        }
Beispiel #10
0
        private static void ProcessCsvLines(LocalTermGroup termGroup, CsvReader csvReader)
        {
            int columnTermSetName        = csvReader.GetColumnIndex("Term Set Name");
            int columnTermSetDescription = csvReader.GetColumnIndex("Term Set Description");
            int columnLcid = csvReader.GetColumnIndex("LCID");
            int columnAvailableForTagging = csvReader.GetColumnIndex("Available for Tagging");
            int columnTermDescription     = csvReader.GetColumnIndex("Term Description");

            int[] columnTermLabels =
            {
                csvReader.GetColumnIndex("Level 1 Term"),
                csvReader.GetColumnIndex("Level 2 Term"),
                csvReader.GetColumnIndex("Level 3 Term"),
                csvReader.GetColumnIndex("Level 4 Term"),
                csvReader.GetColumnIndex("Level 5 Term"),
                csvReader.GetColumnIndex("Level 6 Term"),
                csvReader.GetColumnIndex("Level 7 Term")
            };

            LocalTermSet termSet = null;

            while (csvReader.ReadNextLine())
            {
                // Is it a blank row?
                if (csvReader.Values.All(x => string.IsNullOrWhiteSpace(x)))
                {
                    // Yes, skip it
                    continue;
                }

                string termSetName        = csvReader[columnTermSetName].Trim();
                string termSetDescription = csvReader[columnTermSetDescription].Trim();
                string lcidString         = csvReader[columnLcid].Trim();
                int    currentLcid;
                if (!int.TryParse(lcidString, out currentLcid))
                {
                    currentLcid = termGroup.DefaultLanguageLcid;
                }
                bool availableForTagging = true;
                if (!string.IsNullOrWhiteSpace(csvReader[columnAvailableForTagging]))
                {
                    availableForTagging = bool.Parse(csvReader[columnAvailableForTagging]);
                }
                string termDescription = csvReader[columnTermDescription].Trim();

                var termLabels = new List <string>();
                for (int i = 0; i < columnTermLabels.Length; ++i)
                {
                    int columnIndex = columnTermLabels[i];
                    if (columnIndex < csvReader.Values.Count)
                    {
                        string value = csvReader[columnIndex].Trim();
                        if (string.IsNullOrEmpty(value))
                        {
                            break;
                        }
                        termLabels.Add(value);
                    }
                }

                if (!string.IsNullOrEmpty(termSetName))
                {
                    termSet = termGroup.AddTermSet(Guid.Empty, termSetName);
                    termSet.SetName(termSetName, currentLcid);
                    termSet.Description = termSetDescription;
                }

                if (termSet != null)
                {
                    LocalTermContainer parent = termSet;
                    if (termLabels.Count == 0)
                    {
                        throw new Exception("Missing term label");
                    }

                    foreach (string parentTermLabel in termLabels.Take(termLabels.Count - 1))
                    {
                        LocalTerm newParent;
                        if (!parent.Terms.TryGetByName(parentTermLabel, currentLcid, out newParent))
                        {
                            throw new Exception("No match found for parent term \"" + parentTermLabel + "\"");
                        }

                        parent = newParent;
                    }

                    string    termLabel = termLabels.Last();
                    LocalTerm term      = parent.AddTerm(Guid.Empty, termLabel);
                    term.SetName(termLabel, currentLcid);
                    term.SetDescription(termDescription, currentLcid);
                    term.IsAvailableForTagging = availableForTagging;
                }
            }
        }