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);
 }