private IEnumerable<MtpsNavigationNode> SearchWithinGroup(string searchName, MtpsNavigationNode parent, MtpsNodeCore childLink) { Contract.Requires(!String.IsNullOrEmpty(searchName)); Contract.Requires(parent != null); Contract.Requires(childLink != null); Contract.Ensures(Contract.Result<IEnumerable<MtpsNavigationNode>>() != null); if (null == childLink.SubTreeId) return Enumerable.Empty<MtpsNavigationNode>(); var xmlElement = GetTocXmlElement(childLink.SubTreeId.AssetId, childLink.SubTreeId.Version, childLink.SubTreeId.Locale); if (null == xmlElement) return Enumerable.Empty<MtpsNavigationNode>(); var tocNode = ToNavigationNode(parent, xmlElement); return SearchChildren(searchName, parent, tocNode.ChildLinks); }
private IEnumerable<MtpsNavigationNode> SearchToc(string searchName, MtpsNavigationNode node) { Contract.Requires(!String.IsNullOrEmpty(searchName)); Contract.Requires(node != null); Contract.Ensures(Contract.Result<IEnumerable<MtpsNavigationNode>>() != null); var results = SearchChildren(searchName, node, node.ChildLinks); var nodeFullName = node.GetFullName(); if (searchName.Equals(nodeFullName)) { results = new[] { node }.Concat(results); } return results; }
private IEnumerable<MtpsNavigationNode> SearchChild(string searchName, MtpsNavigationNode parent, MtpsNodeCore childLink) { Contract.Requires(!String.IsNullOrEmpty(searchName)); Contract.Requires(parent != null); Contract.Requires(childLink != null); Contract.Ensures(Contract.Result<IEnumerable<MtpsNavigationNode>>() != null); var tocNode = ToNavigationNode(parent, childLink); return SearchToc(searchName, tocNode); }
private IEnumerable<MtpsNavigationNode> SearchChildren(string searchName, MtpsNavigationNode node, IEnumerable<MtpsNodeCore> children) { Contract.Requires(!String.IsNullOrEmpty(searchName)); Contract.Requires(node != null); Contract.Requires(children != null); Contract.Ensures(Contract.Result<IEnumerable<MtpsNavigationNode>>() != null); // NOTE: while it would be easy to make this parallel it could result in a performance loss // The search collections use enumerable to allow for early search termination when a result matches. // Execution in parallel may cause service requests to be invoked even after the correct nodes have been located. return children .Where(c => !c.IsPhantom) .SelectMany(childNode => { if (childNode.IsNamespace || childNode.IsTypeOrMember) { var fullName = childNode.GetFullName(); if (!String.IsNullOrEmpty(fullName) && searchName.StartsWith(fullName)) { return SearchChild(searchName, node, childNode); } } else if (childNode.IsNodeGroup) { var groupReferenceName = childNode.GetFullName(); if (String.IsNullOrEmpty(groupReferenceName) || searchName.StartsWith(groupReferenceName)){ return SearchWithinGroup(searchName, node, childNode); } } return Enumerable.Empty<MtpsNavigationNode>(); }); }
private string GetUrl(MtpsNavigationNode node) { Contract.Requires(node != null); Contract.Ensures(!String.IsNullOrEmpty(Contract.Result<string>())); var locale = GetBestLocale(node); var id = String.IsNullOrEmpty(node.Alias) ? node.ContentId : node.Alias; return String.Format("http://msdn.microsoft.com/{0}/library/{1}.aspx", locale ?? Locale, id); }