/// <summary> /// Gets the ESD metadata preferred terms related to the specified term /// </summary> /// <param name="termId">The id of the term for which to get related terms</param> /// <param name="termIdToExclude">The id of a term which should not be included even if it is related to the specified term</param> /// <returns>A collection of related terms</returns> public EsdTermCollection GetRelatedTerms(string termId, string termIdToExclude) { // get mappings to related terms string xPath; if (termIdToExclude != null && termIdToExclude.Length > 0) { xPath = String.Format(CultureInfo.InvariantCulture, "ns:Item[@Id='{0}']/ns:RelatedItem[@Id!='{1}']", termId.Trim(), termIdToExclude.Trim()); } else { xPath = String.Format(CultureInfo.InvariantCulture, "ns:Item[@Id='{0}']/ns:RelatedItem", termId.Trim()); } XPathNodeIterator it = this.SelectNodes(xPath); // get details of mapped terms EsdTermCollection terms = new EsdTermCollection(); while (it.MoveNext()) { EsdTerm term = this.GetTerm(it.Current.GetAttribute("Id", ""), EsdPreferredState.Preferred); if (term != null) { terms.Add(term); } } terms.Sort(); return(terms); }
/// <summary> /// Gets the parent ESD metadata terms of the specified term /// </summary> /// <param name="termId">The id of the term for which to get parent terms</param> /// <param name="defaultOnly">ESD metadata lists are polyhierarchical - terms can appear in multiple positions, but before the SKOS alignment each had a single default position</param> /// <returns>A collection of broader terms. If <code>defaultOnly</code> is <code>true</code>, the collection will contain a maximum of one term.</returns> public EsdTermCollection GetBroaderTerms(string termId, bool defaultOnly) { // get mappings to broader terms string xPath; if (defaultOnly) { // account for GCL or all SKOS-compatible lists which don't have default attribute xPath = String.Format(CultureInfo.InvariantCulture, "ns:Item[@Id='{0}']/ns:BroaderItem[@Default='true' or count(@Default)=0]", termId.Trim()); } else { xPath = String.Format(CultureInfo.InvariantCulture, "ns:Item[@Id='{0}']/ns:BroaderItem", termId.Trim()); } XPathNodeIterator it = this.SelectNodes(xPath); // get details of broader terms EsdTermCollection terms = new EsdTermCollection(); while (it.MoveNext()) { EsdTerm term = this.GetTerm(it.Current.GetAttribute("Id", ""), EsdPreferredState.Preferred); if (term != null) { terms.Add(term); } } terms.Sort(); return(terms); }
/// <summary> /// Creates a term from a controlled list on the Electronic Service Delivery (ESD) Standards site at <a href="http://www.esd.org.uk/standards/">http://www.esd.org.uk/standards/</a>. /// </summary> public EsdTerm() { this.nonPreferredTerms = new EsdTermCollection(); this.relatedTerms = new EsdTermCollection(); this.broaderTerms = new EsdTermCollection(); this.childTerms = new EsdTermCollection(); this.equivalentType = EsdEquivalentType.NotSpecified; }
/// <summary> /// Gets ESD metadata terms based on the name of the term /// </summary> /// <param name="termName">The term name to search for</param> /// <param name="exactMatch">true to match the whole name of a term; false to match any part of the term</param> /// <param name="preferredState">Specify whether the term must be preferred or non-preferred</param> /// <returns>A collection of matching terms</returns> /// <remarks>Matching is not case-sensitive. For SKOS-compatible lists (those published after June 2010) the behaviour /// of this method has changed. When a search matches a non-preferred term it used to return the non-preferred term /// as a top-level object alongside preferred terms. For SKOS compatible lists it now returns the preferred term which /// goes with the non-preferred term.</remarks> public EsdTermCollection GetTerms(string termName, bool exactMatch, EsdPreferredState preferredState) { // double-quotes (") are used to delimit xpath strings in this method because it allows apostrophes in the string string xPath = null; if (exactMatch) { switch (preferredState) { case EsdPreferredState.Preferred: xPath = this.skosCompatible ? "ns:Item[ns:Name[translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')=\"{0}\"]]" : "ns:Item[@Preferred='true' and ns:Name[translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')=\"{0}\"]]"; break; case EsdPreferredState.NonPreferred: xPath = this.skosCompatible ? "ns:Item[ns:AlternativeName[translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')=\"{0}\"]]" : "ns:Item[@Preferred='false' and ns:Name[translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')=\"{0}\"]]"; break; case EsdPreferredState.Any: xPath = this.skosCompatible ? "ns:Item[ns:Name[translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')=\"{0}\"] or ns:AlternativeName[translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')=\"{0}\"]]" : "ns:Item[ns:Name[translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')=\"{0}\"]]"; break; } } else { switch (preferredState) { case EsdPreferredState.Preferred: xPath = this.skosCompatible ? "ns:Item[ns:Name[contains(translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), \"{0}\")]]" : "ns:Item[@Preferred='true' and ns:Name[contains(translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), \"{0}\")]]"; break; case EsdPreferredState.NonPreferred: xPath = this.skosCompatible ? "ns:Item[ns:AlternativeName[contains(translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), \"{0}\")]]" : "ns:Item[@Preferred='false' and ns:Name[contains(translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), \"{0}\")]]"; break; case EsdPreferredState.Any: xPath = this.skosCompatible ? "ns:Item[ns:Name[contains(translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), \"{0}\")] or ns:AlternativeName[contains(translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), \"{0}\")]]" : "ns:Item[ns:Name[contains(translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), \"{0}\")]]"; break; } } XPathNodeIterator it = this.SelectNodes(String.Format(CultureInfo.InvariantCulture, xPath, termName.Trim().ToLower(CultureInfo.CurrentCulture))); EsdTermCollection terms = new EsdTermCollection(); while (it.MoveNext()) { terms.Add(this.GetEsdTermFromXml(it.Current)); } terms.Sort(); return(terms); }
/// <summary> /// Gets the descendant terms of the specified ESD metadata term. /// </summary> /// <param name="ancestorTerm">The ancestor term.</param> /// <param name="recurseLevels">How many levels down the tree to go. If <c>-1</c>, get all descendants.</param> /// <returns>The original term with its ChildTerms property populated</returns> public EsdTerm GetDescendantTerms(EsdTerm ancestorTerm, int recurseLevels) { if (recurseLevels == 0) { return(ancestorTerm); // no point searching if results aren't wanted } EsdTermCollection ancestorInCollection = GetDescendantTerms(ancestorTerm, recurseLevels, true); return((ancestorInCollection.Count == 1) ? ancestorInCollection[0] : null); }
/// <summary> /// Gets the descendant terms of the specified ESD metadata term. /// </summary> /// <param name="ancestorTerm">The ancestor term.</param> /// <param name="recurseLevels">How many levels down the tree to go. If <c>-1</c>, get all descendants.</param> /// <param name="updateAncestorTerm">if set to <c>true</c> updates the ancestor term and returns it in a 1-item collection; if <c>false returns a flat collection of all ancestor terms</c></param> private EsdTermCollection GetDescendantTerms(EsdTerm ancestorTerm, int recurseLevels, bool updateAncestorTerm) { EsdTermCollection descendantTerms = new EsdTermCollection(); EsdTermCollection currentLevel = new EsdTermCollection(); currentLevel.Add(ancestorTerm); EsdTermCollection nextLevel = new EsdTermCollection(); while (recurseLevels > 0 || recurseLevels == -1) { foreach (EsdTerm currentTerm in currentLevel) { EsdTermCollection childTerms = this.GetChildTerms(currentTerm.Id); // add those child terms to the overall collection, and to the collection for querying the next level foreach (EsdTerm childTerm in childTerms) { if (updateAncestorTerm) { currentTerm.ChildTerms.Add(childTerm); } else { descendantTerms.Add(childTerm); } nextLevel.Add(childTerm); } } // If there are no more children, break out // This is essential for the "all levels" setting to prevent an infinite loop if (nextLevel.Count == 0) { break; } // otherwise step down to find children of these children currentLevel = nextLevel; nextLevel = new EsdTermCollection(); // don't use .Clear() because that clears currentLevel if (recurseLevels > 0) { recurseLevels--; } } if (updateAncestorTerm) { descendantTerms.Add(ancestorTerm); } return(descendantTerms); }
/// <summary> /// Gets the non-preferred terms for the specified ESD metadata preferred term /// </summary> /// <param name="preferredTermId">The id of the preferred term for which to get non-preferred terms</param> /// <returns>A collection of non-preferred terms</returns> public EsdTermCollection GetNonPreferredTerms(string preferredTermId) { string xPath = this.skosCompatible ? "ns:Item[@Id='{0}']/ns:AlternativeName" : "ns:Item[@Preferred='false' and ns:UseItem[@Id='{0}']]"; xPath = String.Format(CultureInfo.InvariantCulture, xPath, preferredTermId.Trim()); XPathNodeIterator it = this.SelectNodes(xPath); EsdTermCollection terms = new EsdTermCollection(); while (it.MoveNext()) { EsdTerm term = this.GetEsdTermFromXml(it.Current); terms.Add(term); } terms.Sort(); return(terms); }
/// <summary> /// Gets the ESD metadata terms mapped to the specified terms in another ESD controlled list /// </summary> /// <param name="esdListXml">The XML file of the ESD controlled list containing the mapped terms</param> /// <param name="termsToMap">The terms for which to get mapped terms</param> /// <param name="mapForwards">If false, map from list B to list A, rather than list A to list B</param> /// <returns>A collection of mapped terms</returns> public EsdTermCollection GetMappedTerms(EsdControlledList esdListXml, EsdTermCollection termsToMap, bool mapForwards) { EsdTermCollection mappedTerms = new EsdTermCollection(); foreach (EsdTerm termToMap in termsToMap) { EsdTermCollection termsFound = this.GetMappedTerms(esdListXml, termToMap.Id, mapForwards); foreach (EsdTerm foundTerm in termsFound) { if (!mappedTerms.Contains(foundTerm)) { mappedTerms.Add(foundTerm); } } } return(mappedTerms); }
/// <summary> /// Gets the child terms of the specified ESD metadata term /// </summary> /// <param name="termId">The id of the term to get</param> /// <returns>A collection of child terms</returns> public EsdTermCollection GetChildTerms(string termId) { // get child terms string xPath = String.Format(CultureInfo.InvariantCulture, "ns:Item[ns:BroaderItem[@Id='{0}']]", termId.Trim()); XPathNodeIterator it = this.SelectNodes(xPath); EsdTermCollection terms = new EsdTermCollection(); while (it.MoveNext()) { EsdTerm term = this.GetEsdTermFromXml(it.Current); if (term != null) { terms.Add(term); } } terms.Sort(); return(terms); }
/// <summary> /// Checks the terms in the control against the specified controlled list /// </summary> /// <returns>true if all terms are valid; false if any one term is not valid (matching is not case sensitive)</returns> protected override bool EvaluateIsValid() { // If an instance of this validator is run more than once on one request, just return the same result and don't do all the work again. // Not that anyone would run it more than once on one request, unless it was really inefficient (SharePoint field controls). if (cachedIsValid != null) { return((bool)cachedIsValid); } // check the list was specified if (this.controlledListName == null || this.controlledListName.Length == 0) { throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, "The ControlledListName property was not set for {0}", this.GetType().ToString())); } // get control to validate and get its value Control controlToValidate = this.Parent.FindControl(this.ControlToValidate); string valueToValidate = String.Empty; // If it's a textbox ensure it's in a variable we can use later to put a tidied-up value back into the textbox TextBox textboxToValidate = controlToValidate as TextBox; if (textboxToValidate != null) { // Trim off any trailing semi-colon separator valueToValidate = textboxToValidate.Text.TrimEnd(' ', ';'); } else { // Maybe it's a list of some kind? Test with cast rather than .GetType() == typeof(ListControl) // because need to support customised derived types of control. ListControl listToValidate = controlToValidate as ListControl; if (listToValidate != null) { EsdTermCollection selectedTerms = new EsdTermCollection(); foreach (ListItem item in listToValidate.Items) { if (item.Selected) { EsdTerm selectedTerm = new EsdTerm(); selectedTerm.Id = item.Value; selectedTerm.Text = item.Text; selectedTerms.Add(selectedTerm); } } valueToValidate = selectedTerms.ToString(); } else { // No other control type supported yet - throw a useful error for the developer throw new ArgumentException(String.Format("The control type matched by the ControlToValidate property, {0}, is not supported by the EsdTermValidator", controlToValidate.GetType().ToString())); } } // this isn't a required validator if (valueToValidate.Length == 0) { this.cachedIsValid = true; return(true); } // get the XML we need EsdControlledList esdListXml = EsdControlledList.GetControlledList(this.controlledListName, false); // box has semi-colon separated list of preferred terms string[] searchTerms; if (this.multipleTerms) { valueToValidate = valueToValidate.Trim(' ', ';'); searchTerms = valueToValidate.Split(';'); } else { searchTerms = new string[1]; searchTerms[0] = valueToValidate.Trim(); } // If we only want preferred terms, search for any term then we can convert it to the preferred term EsdPreferredState searchState = (this.preferredState == EsdPreferredState.Preferred ? EsdPreferredState.Any : this.preferredState); // Search for terms and gather results StringBuilder termBuilder = new StringBuilder(); this.invalidTerms = new ArrayList(); this.matchedTerms.Clear(); List <string> matchedTermIds = new List <string>(); int totalMatchedTerms = 0; string trimmedSearch; Regex numeric = new Regex("^[0-9]+$"); foreach (string searchTerm in searchTerms) { trimmedSearch = searchTerm.Trim(); if (trimmedSearch.Length == 0) { continue; } if (this.termIdsAllowed && numeric.IsMatch(trimmedSearch)) { if (this.allowedTerms.Count > 0) { // Validate the text of the term against just those terms in the AllowedTerms collection int termIndex = this.allowedTerms.IndexOfId(trimmedSearch, this.preferredState); // If that didn't work and we want preferred terms, see if it matches a non-preferred term and the preferred term is allowed if (this.preferredState == EsdPreferredState.Preferred && termIndex == -1) { EsdTerm matchedTerm = esdListXml.GetTerm(trimmedSearch, EsdPreferredState.NonPreferred); if (matchedTerm != null) { matchedTerm = esdListXml.GetPreferredTerm(matchedTerm.ConceptId); if (matchedTerm != null) { termIndex = this.allowedTerms.IndexOf(matchedTerm.Text, EsdPreferredState.Preferred); } } } if (termIndex > -1) { EsdTerm matchedTerm = this.allowedTerms[termIndex]; totalMatchedTerms++; // Add it unless it's a duplicate if (!matchedTermIds.Contains(matchedTerm.Id)) { this.matchedTerms.Add(matchedTerm); if (termBuilder.Length > 0) { termBuilder.Append("; "); } termBuilder.Append(matchedTerm.Id); matchedTermIds.Add(matchedTerm.Id); } } else { this.invalidTerms.Add(trimmedSearch); if (termBuilder.Length > 0) { termBuilder.Append("; "); } termBuilder.Append(trimmedSearch); } } else { EsdTerm matchedTerm = esdListXml.GetTerm(trimmedSearch, searchState); if (matchedTerm != null) { totalMatchedTerms++; // If we want preferred terms, ensure we have the preferred term if (this.preferredState == EsdPreferredState.Preferred && !matchedTerm.Preferred) { matchedTerm = esdListXml.GetPreferredTerm(matchedTerm.ConceptId); } // Add it unless it's a duplicate if (!matchedTermIds.Contains(matchedTerm.Id)) { this.matchedTerms.Add(matchedTerm); if (termBuilder.Length > 0) { termBuilder.Append("; "); } termBuilder.Append(matchedTerm.Id); matchedTermIds.Add(matchedTerm.Id); } } else { this.invalidTerms.Add(trimmedSearch); if (termBuilder.Length > 0) { termBuilder.Append("; "); } termBuilder.Append(trimmedSearch); } } } else { if (this.allowedTerms.Count > 0) { // Validate the text of the term against just those terms in the AllowedTerms collection int termIndex = this.allowedTerms.IndexOf(trimmedSearch, this.preferredState); // If that didn't work and we want preferred terms, see if it matches a non-preferred term and the preferred term is allowed if (this.preferredState == EsdPreferredState.Preferred && termIndex == -1) { EsdTermCollection matchedTerms = esdListXml.GetTerms(trimmedSearch, true, EsdPreferredState.NonPreferred); if (matchedTerms.Count == 1) { EsdTerm matchedTerm = esdListXml.GetPreferredTerm(matchedTerms[0].ConceptId); if (matchedTerm != null) { termIndex = this.allowedTerms.IndexOf(matchedTerm.Text, EsdPreferredState.Preferred); } } } if (termIndex > -1) { EsdTerm matchedTerm = this.allowedTerms[termIndex]; totalMatchedTerms++; // Add it unless it's a duplicate if (!matchedTermIds.Contains(matchedTerm.Id)) { this.matchedTerms.Add(matchedTerm); if (termBuilder.Length > 0) { termBuilder.Append("; "); } termBuilder.Append(matchedTerm.Text); matchedTermIds.Add(matchedTerm.Id); } } else { this.invalidTerms.Add(trimmedSearch); if (termBuilder.Length > 0) { termBuilder.Append("; "); } termBuilder.Append(trimmedSearch); } } else { // Validate the text of the term against the full controlled list EsdTermCollection terms = esdListXml.GetTerms(trimmedSearch, true, searchState); if (terms.Count == 1) { totalMatchedTerms++; // If we want preferred terms, ensure we have the preferred term EsdTerm matchedTerm = terms[0]; if (this.preferredState == EsdPreferredState.Preferred && !matchedTerm.Preferred) { matchedTerm = esdListXml.GetPreferredTerm(matchedTerm.ConceptId); } // Add it unless it's a duplicate if (!matchedTermIds.Contains(matchedTerm.Id)) { this.matchedTerms.Add(matchedTerm); if (termBuilder.Length > 0) { termBuilder.Append("; "); } termBuilder.Append(matchedTerm.Text); matchedTermIds.Add(matchedTerm.Id); } } else { this.invalidTerms.Add(trimmedSearch); if (termBuilder.Length > 0) { termBuilder.Append("; "); } termBuilder.Append(trimmedSearch); } } } } // if control had user-editable (rather than selectable) values, update control with case-corrected terms if (textboxToValidate != null) { textboxToValidate.Text = termBuilder.ToString(); } // return true if terms valid; false if any one term is not valid // totalMatchedTerms may not be the same as this.MatchedTerms.Count because totalMatchedTerms is incremented for a duplicate if (totalMatchedTerms == searchTerms.Length) { this.cachedIsValid = true; return(true); // all terms were matched } else { StringBuilder errorBuilder = new StringBuilder(); string listName = esdListXml.AbbreviatedName; string termDelimiter = "'"; // build error message with singular grammar if (this.invalidTerms.Count == 1) { if (this.allowedTerms.Count > 0) { errorBuilder.Append(termDelimiter).Append(this.invalidTerms[0]).Append(termDelimiter).Append(" is not one of the ").Append(listName).Append(" terms allowed here"); } else { errorBuilder.Append(termDelimiter).Append(this.invalidTerms[0]).Append(termDelimiter).Append(" is not a"); if (listName.StartsWith("A") || listName.StartsWith("E") || listName.StartsWith("I") || listName.StartsWith("O") || listName.StartsWith("U")) { errorBuilder.Append("n"); } errorBuilder.Append(" ").Append(listName).Append(" "); if (this.preferredState == EsdPreferredState.Preferred) { errorBuilder.Append("preferred"); } else if (this.preferredState == EsdPreferredState.NonPreferred) { errorBuilder.Append("non-preferred"); } errorBuilder.Append(" term"); } } else { // build error message with plural grammar for (short i = 0; i < this.invalidTerms.Count; i++) { if (errorBuilder.Length > 0) { if (i == (this.invalidTerms.Count - 1)) { errorBuilder.Append(" and "); } else { errorBuilder.Append(", "); } } errorBuilder.Append(termDelimiter).Append(this.invalidTerms[i]).Append(termDelimiter); } if (this.allowedTerms.Count > 0) { errorBuilder.Append(" are not among the ").Append(listName).Append(" terms allowed here"); } else { errorBuilder.Append(" are not ").Append(listName).Append(" "); if (this.preferredState == EsdPreferredState.Preferred) { errorBuilder.Append("preferred"); } else if (this.preferredState == EsdPreferredState.NonPreferred) { errorBuilder.Append("non-preferred"); } errorBuilder.Append(" terms"); } } this.ErrorMessage = errorBuilder.ToString(); this.cachedIsValid = false; return(false); } }
/// <summary> /// Enables processing of HTTP Web requests by a custom HttpHandler that implements the <see cref="T:System.Web.IHttpHandler"/> interface. /// </summary> /// <param name="context">An <see cref="T:System.Web.HttpContext"/> object that provides references to the intrinsic server objects (for example, Request, Response, Session, and Server) used to service HTTP requests.</param> public void ProcessRequest(HttpContext context) { // If there is no query, just return no results string searchTerm = String.Empty; bool formatResultsAsJSON = true; if (!String.IsNullOrEmpty(context.Request.QueryString["term"])) { searchTerm = context.Request.QueryString["term"]; // JQueryUI plugin } else if (!String.IsNullOrEmpty(context.Request.QueryString["q"])) { searchTerm = context.Request.QueryString["q"]; // old autocomplete plugin formatResultsAsJSON = false; } if (String.IsNullOrEmpty(searchTerm)) { return; } // Check we know which list to query if (String.IsNullOrEmpty(context.Request.QueryString["list"])) { throw new ArgumentException("The controlled list must be specified in the querystring as list=<abbreviated name of list>"); } // Load the list EsdControlledList controlledList = EsdControlledList.GetControlledList(context.Request.QueryString["list"]); List <string> termsFound = new List <string>(); // Are the valid terms limited to a specific list of allowed terms? if (String.IsNullOrEmpty(context.Request.QueryString["allowed"])) { // If not limited, do a standard search for the search term. Get non-preferred terms too because // they're there to help the user find the appropriate preferred term. EsdTermCollection results = controlledList.GetTerms(searchTerm, false, EsdPreferredState.Any); // Return results as one per line, with non-preferred terms suffixed by a separator and the appropriate preferred term foreach (EsdTerm term in results) { if (term.Text.ToUpperInvariant().Contains(searchTerm.ToUpperInvariant())) { if (term.Preferred) { termsFound.Add(term.Text); // Add non-preferred terms suffixing them with a separator and the appropriate preferred term EsdTermCollection nonPreferredTerms = controlledList.GetNonPreferredTerms(term.Id); foreach (EsdTerm nonPreferredTerm in nonPreferredTerms) { if (nonPreferredTerm.Text.Contains(searchTerm)) { termsFound.Add(nonPreferredTerm.Text + "|" + term.Text); } } } else { // Non-preferred terms will only be directly returned like this from an XML file published before June 2010, which uses the pre-SKOS schema termsFound.Add(term.Text + "|" + controlledList.GetPreferredTerm(term.ConceptId).Text); } } } } else { // Only a restricted set of terms are allowed, passed as semi-colon separated list of ids in the querystring. // Use IDs rather than terms to limit length of querystring. EsdTermCollection allowed = new EsdTermCollection(); allowed.ReadString(context.Request.QueryString["allowed"]); // Look up each allowed term (we knew those) and its non-preferred terms (those are new) foreach (EsdTerm term in allowed) { // ReadString has put the ids into the Text property, so use that for search to get the // text of the preferred term. EsdTerm preferredTerm = controlledList.GetTerm(term.Text, EsdPreferredState.Preferred); if (preferredTerm.Text.Contains(searchTerm)) { termsFound.Add(preferredTerm.Text); } // Add non-preferred terms suffixing them with a separator and the appropriate preferred term EsdTermCollection nonPreferredTerms = controlledList.GetNonPreferredTerms(preferredTerm.Id); foreach (EsdTerm nonPreferredTerm in nonPreferredTerms) { if (nonPreferredTerm.Text.Contains(searchTerm)) { termsFound.Add(nonPreferredTerm.Text + "|" + preferredTerm.Text); } } } } // Sort and return results termsFound.Sort(); if (formatResultsAsJSON) { context.Response.Write("["); int len = termsFound.Count; for (int i = 0; i < len; i++) { int dividerPos = termsFound[i].IndexOf("|"); if (dividerPos == -1) { // preferred term needs only a value property context.Response.Write("{ \"label\": \"" + termsFound[i].Replace(searchTerm, "<em>" + searchTerm + "</em>") + "\", \"value\": \"" + termsFound[i] + "\" }"); } else { string[] parts = termsFound[i].Split(new char[] { '|' }, 2, StringSplitOptions.RemoveEmptyEntries); // non-preferred term needs label and value context.Response.Write("{ \"label\": \"" + parts[0].Replace(searchTerm, "<em>" + searchTerm + "</em>") + " – use " + parts[1] + "\", \"value\": \"" + parts[1] + "\" }"); } if (i < len - 1) { context.Response.Write(","); } } context.Response.Write("]"); } else { // one-per-line format for old autocomplete plugin foreach (string result in termsFound) { context.Response.Write(result + Environment.NewLine); } } }
/// <summary> /// Gets the ESD metadata terms mapped to the specified term in another ESD controlled list /// </summary> /// <param name="esdListXml">The XML file of the ESD controlled list containing the mapped terms</param> /// <param name="termId">The id of the term for which to get mapped terms</param> /// <param name="mapForwards">If false, map from list B to list A, rather than list A to list B</param> /// <param name="termIdToExclude">The id of a term which should not be included even if it is mapped to the specified term</param> /// <returns>A collection of mapped terms</returns> public EsdTermCollection GetMappedTerms(EsdControlledList esdListXml, string termId, bool mapForwards, string termIdToExclude) { if (termId == null) { return(new EsdTermCollection()); } // get mappings string xPath; if (mapForwards) { xPath = String.Format(CultureInfo.InvariantCulture, "ns:ItemMapping[ns:From/ns:Item[@Id='{0}']]", termId.Trim()); } else { xPath = String.Format(CultureInfo.InvariantCulture, "ns:ItemMapping[ns:To/ns:Item[@Id='{0}']]", termId.Trim()); } XPathNodeIterator it = this.SelectNodes(xPath); // get details of mapped terms EsdTermCollection terms = new EsdTermCollection(); if (mapForwards) { if (termIdToExclude != null && termIdToExclude.Length > 0) { xPath = String.Format(CultureInfo.InvariantCulture, "ns:To/ns:Item[@Id!='{0}']", termIdToExclude); } else { xPath = "ns:To/ns:Item"; } } else { if (termIdToExclude != null && termIdToExclude.Length > 0) { xPath = String.Format(CultureInfo.InvariantCulture, "ns:From/ns:Item[@Id!='{0}']", termIdToExclude); } else { xPath = "ns:From/ns:Item"; } } while (it.MoveNext()) { XPathNodeIterator mappingNode = this.SelectNodes(xPath, it.Current); if (mappingNode.Count == 1) { mappingNode.MoveNext(); EsdTerm term = esdListXml.GetTerm(mappingNode.Current.GetAttribute("Id", ""), EsdPreferredState.Preferred); if (term != null) { terms.Add(term); } } } terms.Sort(); return(terms); }
/// <summary> /// Gets the ESD metadata terms mapped to the specified terms in another ESD controlled list /// </summary> /// <param name="esdListXml">The XML file of the ESD controlled list containing the mapped terms</param> /// <param name="termsToMap">The terms for which to get mapped terms</param> /// <returns>A collection of mapped terms</returns> public EsdTermCollection GetMappedTerms(EsdControlledList esdListXml, EsdTermCollection termsToMap) { return(this.GetMappedTerms(esdListXml, termsToMap, true)); }