public static void ReplaceSelfLinks(IOpenSearchable entity, NameValueCollection parameters, IOpenSearchResultCollection osr, Func<IOpenSearchResultItem,OpenSearchDescription,string,string> entryTemplate, string contentType)
        {
            IOpenSearchResultCollection feed = osr;

            var matchLinks = feed.Links.Where(l => l.RelationshipType == "self").ToArray();
            foreach (var link in matchLinks) {
                feed.Links.Remove(link);
            }

            OpenSearchDescription osd = null;
            if (entity is IProxiedOpenSearchable) {
                osd = ((IProxiedOpenSearchable)entity).GetProxyOpenSearchDescription();
            } else {
                osd = entity.GetOpenSearchDescription();
            }
            if (OpenSearchFactory.GetOpenSearchUrlByType(osd, contentType) == null)
                return;

            NameValueCollection newNvc = new NameValueCollection(parameters);
            NameValueCollection osparams = OpenSearchFactory.GetOpenSearchParameters(OpenSearchFactory.GetOpenSearchUrlByType(osd, contentType));
            newNvc.AllKeys.FirstOrDefault(k => {
                if (string.IsNullOrEmpty(OpenSearchFactory.GetParamNameFromId(osparams, k)))
                    newNvc.Remove(k);
                return false;
            });
            osparams.AllKeys.FirstOrDefault(k => {
                Match matchParamDef = Regex.Match(osparams[k], @"^{([^?]+)\??}$");
                if (!matchParamDef.Success)
                    newNvc.Set(k, osparams[k]);
                return false;
            });

            UriBuilder myUrl = new UriBuilder(OpenSearchFactory.GetOpenSearchUrlByType(osd, contentType).Template);
            string[] queryString = Array.ConvertAll(newNvc.AllKeys, key => string.Format("{0}={1}", key, newNvc[key]));
            myUrl.Query = string.Join("&", queryString);

            feed.Links.Add(new SyndicationLink(myUrl.Uri, "self", "Reference link", contentType, 0));
            feed.Id = myUrl.ToString();

            foreach (IOpenSearchResultItem item in feed.Items) {
                matchLinks = item.Links.Where(l => l.RelationshipType == "self").ToArray();
                foreach (var link in matchLinks) {
                    item.Links.Remove(link);
                }
                string template = entryTemplate(item, osd, contentType);
                if (template != null) {
                    item.Links.Add(new SyndicationLink(new Uri(template), "self", "Reference link", contentType, 0));
                    item.Id = template;
                }
            }
        }
        public static void ReplaceOpenSearchDescriptionLinks(IOpenSearchable entity, IOpenSearchResultCollection osr)
        {
            IOpenSearchResultCollection feed = osr;

            var matchLinks = feed.Links.Where(l => l.RelationshipType == "search").ToArray();
            foreach (var link in matchLinks) {
                feed.Links.Remove(link);
            }

            OpenSearchDescription osd;
            if (entity is IProxiedOpenSearchable)
                osd = ((IProxiedOpenSearchable)entity).GetProxyOpenSearchDescription();
            else
                osd = entity.GetOpenSearchDescription();
            OpenSearchDescriptionUrl url = OpenSearchFactory.GetOpenSearchUrlByRel(osd, "self");
            Uri uri;
            if (url != null)
                uri = new Uri(url.Template);
            else
                uri = osd.Originator;
            if (uri != null)
                feed.Links.Add(new SyndicationLink(uri, "search", "OpenSearch Description link", "application/opensearchdescription+xml", 0));
        }
        /// <summary>
        /// Create an OpenSearchRequest based on the IOpenSearchable entity, type and parameters.
        /// </summary>
        /// <description>
        /// This method is the basic default implementation for creating OpenSearchRequest. It supports only 2 schemes:
        /// 1) file:// that will create a FileOpenSearchRequest
        /// 2) http:// that will create an HttpOpenSearchRequest
        /// <param name="entity">IOpenSearchable Entity.</param>
        /// <param name="type">MimeType of the request.</param>
        /// <param name="parameters">Parameters of the request.</param>
        public static OpenSearchRequest Create(IOpenSearchable entity, QuerySettings querySettings, NameValueCollection parameters)
        {
            OpenSearchDescription osd = entity.GetOpenSearchDescription();

            OpenSearchDescriptionUrl url = OpenSearchFactory.GetOpenSearchUrlByType(osd, querySettings.PreferredContentType);

            if (url == null) throw new InvalidOperationException(string.Format("Could not find a URL template for entity {0} with type {1}", entity.Identifier, querySettings.PreferredContentType));

            OpenSearchUrl queryUrl = OpenSearchFactory.BuildRequestUrlForTemplate(url, parameters, entity.GetOpenSearchParameters(querySettings.PreferredContentType), querySettings);

            OpenSearchRequest request = null;

            switch (queryUrl.Scheme) {
                case "http":
                case "https":
                    request = new HttpOpenSearchRequest(queryUrl, querySettings.PreferredContentType);
                    ((HttpOpenSearchRequest)request).TimeOut = 60000;
                    break;
                case "file":
                    request = new FileOpenSearchRequest(queryUrl, querySettings.PreferredContentType);
                    break;
            }

            request.OriginalParameters = parameters;

            return request;
        }
        private void PrintOpenSearchDescription(string arg)
        {
            Match  argMatch  = argRegex.Match(arg);
            string type      = argMatch.Groups[1].Value;
            string paramName = (argMatch.Groups[2].Success ? argMatch.Groups[3].Value : null);

            bool typeFound  = false;
            bool paramFound = false;

            dataModelParameters = PrepareDataModelParameters();
            dataModel           = DataModel.CreateFromArgs(queryModelArg, dataModelParameters);
            OpenSearchableFactorySettings settings = new OpenSearchableFactorySettings(ose);

            settings.MaxRetries = retryAttempts;
            List <Uri>            baseUrls = InitializeUrl();
            IOpenSearchable       entity   = dataModel.CreateOpenSearchable(baseUrls, queryFormatArg, ose, netCreds, settings);
            OpenSearchDescription osd      = entity.GetOpenSearchDescription();

            using (Stream outputStream = InitializeOutputStream()) {
                using (StreamWriter sw = new StreamWriter(outputStream)) {
                    if (type == "types")
                    {
                        sw.WriteLine("Formats");
                        sw.WriteLine("{0,-10}{1,-10}{2,-60}", "Format", "Supported", "MIME type");
                        sw.WriteLine("{0,-10}{1,-10}{2,-60}", "======", "=========", "=========");

                        foreach (OpenSearchDescriptionUrl url in osd.Url)
                        {
                            if (url.Relation == "self")
                            {
                                continue;
                            }

                            bool isFormat = false;
                            foreach (IOpenSearchEngineExtension osee in ose.Extensions.Values)
                            {
                                if (osee.DiscoveryContentType == url.Type)
                                {
                                    isFormat = true;
                                    break;
                                }
                            }
                            string urlShortType = GetUrlShortType(url.Type);

                            sw.WriteLine("{0,-14}{1,-6}{2,-40}", urlShortType == url.Type ? "-" : urlShortType, isFormat ? "*" : " ", url.Type);
                        }
                    }
                    else
                    {
                        foreach (OpenSearchDescriptionUrl url in osd.Url)
                        {
                            if (url.Relation == "self")
                            {
                                continue;
                            }

                            string urlShortType = GetUrlShortType(url.Type);
                            if (type != "full" && type != urlShortType)
                            {
                                continue;
                            }

                            typeFound = true;

                            bool isFormat = false;
                            foreach (IOpenSearchEngineExtension osee in ose.Extensions.Values)
                            {
                                if (osee.DiscoveryContentType == url.Type)
                                {
                                    isFormat = true;
                                    break;
                                }
                            }
                            sw.Write("Search URL type: {0}", url.Type);
                            if (isFormat)
                            {
                                sw.Write(" (format: {0})", urlShortType);
                            }
                            sw.WriteLine();

                            int qmPos = url.Template.IndexOf('?');
                            if (qmPos == -1)
                            {
                                continue;
                            }

                            string queryString = url.Template.Substring(qmPos + 1);

                            if (paramName == null)
                            {
                                sw.WriteLine("Parameters");
                                sw.WriteLine("{0,-22}{1,-40} M O R P S (mandatory, options, range, pattern, step)", "Name", "Description/title");
                                sw.WriteLine("{0,-22}{1,-40} ---------", "----", "-----------------");
                            }

                            MatchCollection paramMatches = paramRegex.Matches(queryString);
                            foreach (Match paramMatch in paramMatches)
                            {
                                string name       = paramMatch.Groups[1].Value;
                                string identifier = paramMatch.Groups[2].Value;
                                bool   mandatory  = !paramMatch.Groups[3].Success;
                                string title      = GetParameterDescription(identifier);
                                bool   options    = false;
                                bool   range      = false;
                                bool   pattern    = false;
                                bool   step       = false;

                                OpenSearchDescriptionUrlParameter param = null;
                                if (url.Parameters != null)
                                {
                                    foreach (OpenSearchDescriptionUrlParameter p in url.Parameters)
                                    {
                                        if (p.Name == name)
                                        {
                                            param = p;
                                        }
                                    }
                                }

                                if (param != null)
                                {
                                    title   = param.Title;
                                    options = param.Options != null && param.Options.Count != 0;
                                    range   = param.Maximum != null || param.MinInclusive != null || param.MaxInclusive != null || param.MinExclusive != null || param.MaxExclusive != null;
                                    pattern = param.Pattern != null;
                                    step    = param.Step != null;
                                }

                                if (paramName == null)
                                {
                                    if (title != null && title.Length > 40)
                                    {
                                        title = String.Format("{0}...", title.Substring(0, 37));
                                    }
                                    sw.WriteLine("- {0,-20}{1,-40} {2,-2}{3,-2}{4,-2}{5,-2}{6,-2}",
                                                 name,
                                                 title,
                                                 mandatory ? "M" : "-",
                                                 options ? "O" : "-",
                                                 range ? "R" : "-",
                                                 pattern ? "P" : "-",
                                                 step ? "S" : "-"
                                                 );
                                }

                                if (type != "full" && paramName != name)
                                {
                                    continue;
                                }

                                paramFound = true;
                                if (paramName != null)
                                {
                                    sw.WriteLine("- Parameter: {0}", name);
                                    sw.WriteLine("    Description/title: {0}", title);
                                }
                                if (options)
                                {
                                    sw.WriteLine("    Options:");
                                    sw.WriteLine("    {0,-22} {1,-40}", "Value", "Label/description");
                                    sw.WriteLine("    {0,-22} {1,-40}", "-----", "-----------------");
                                    foreach (OpenSearchDescriptionUrlParameterOption o in param.Options)
                                    {
                                        sw.WriteLine("    - {0,-20} {1,-40}", o.Value, o.Label);
                                    }
                                }
                                if (range)
                                {
                                    string min = (param.MinExclusive != null ? param.MinExclusive : param.MinInclusive != null ? param.MinInclusive : param.Minimum);
                                    string max = (param.MaxExclusive != null ? param.MaxExclusive : param.MaxInclusive != null ? param.MaxInclusive : param.Maximum);
                                    sw.WriteLine("    Range: {0} {2} value {3} {1}", min, max, param.MinExclusive == null ? "<=" : "<", param.MaxExclusive == null ? "<=" : "<");
                                }
                                if (pattern)
                                {
                                    sw.WriteLine("    Pattern: {0}", param.Pattern);
                                }
                                if (step)
                                {
                                    sw.WriteLine("    Step: {0}", param.Step);
                                }
                            }
                            sw.WriteLine();


                            //sw.WriteLine("URL {0} {1} {2}", url.Type, url.Relation, url.Template);
                        }
                    }
                    sw.Close();
                }
            }

            if (!typeFound && type != "types" && type != "full")
            {
                log.Error("URL Type not found");
            }
            else if (!paramFound && paramName != null)
            {
                log.Error("Parameter not found");
            }
        }
        private bool ProcessAlternative(List <Uri> uri, List <NetworkCredential> credential, ref bool isAtomFeedPartial, ref bool canceled)
        {
            // Find OpenSearch Entity
            IOpenSearchable entity = null;
            int             retry  = retryAttempts;
            int             index  = 1;

            while (retry >= 0)
            {
                // Perform the query
                try {
                    OpenSearchableFactorySettings settings = new OpenSearchableFactorySettings(ose);
                    settings.MaxRetries = retryAttempts;
                    entity = dataModel.CreateOpenSearchable(uri, queryFormatArg, ose, credential, settings);
                    index  = entity.GetOpenSearchDescription().DefaultUrl.IndexOffset;
                    log.Debug("IndexOffset : " + index);
                    break;
                } catch (Exception e) {
                    log.Warn(e.Message);
                    if (retry == 0)
                    {
                        throw;
                    }
                    retry--;
                    searchCache.ClearCache(".*", DateTime.Now);
                }
            }



            NameValueCollection parameters = PrepareQueryParameters(entity);
            string startIndex = parameters.Get("startIndex");

            if (startIndex != null)
            {
                index = int.Parse(startIndex);
            }

            NameValueCollection parametersNvc;

            IOpenSearchResultCollection osr = null;
            long totalCount = 0;

            log.DebugFormat("{0} entries requested", totalResults);

            if (outputStarted)
            {
                return(false);
            }

            while (totalResults > 0)
            {
                bool   closeOutputStream = true;
                Stream outputStream      = null;
                log.DebugFormat("startIndex: {0}", index);
                parametersNvc = ResolveParameters(parameters, entity);

                // Initialize the output stream
                if (outputStream == null)
                {
                    outputStream = InitializeOutputStream(index);
                }
                else
                {
                    closeOutputStream = false;
                }

                retry = retryAttempts;
                while (retry >= 0)
                {
                    if (canceled)
                    {
                        return(false);
                    }
                    // Perform the query
                    log.Debug("Launching query...");
                    try {
                        osr = QueryOpenSearch(ose, entity, parametersNvc);
                        isAtomFeedPartial = false;
                        break;
                    } catch (AggregateException ae) {
                        if (retry == 0)
                        {
                            throw ae;
                        }
                        foreach (Exception e in ae.InnerExceptions)
                        {
                            log.Warn("Exception " + e.Message);
                        }
                        retry--;
                        searchCache.ClearCache(".*", DateTime.Now);
                    } catch (KeyNotFoundException e) {
                        log.Error("Query not found : " + e.Message);
                        throw e;
                    } catch (PartialAtomException e) {
                        if (retry == 0)
                        {
                            osr = e.PartialOpenSearchResultCollection;
                            isAtomFeedPartial = true;
                        }
                        retry--;
                        searchCache.ClearCache(".*", DateTime.Now);
                    } catch (ThreadAbortException) {
                    } catch (Exception e) {
                        if (retry == 0)
                        {
                            throw;
                        }

                        log.Warn("Exception " + e.Message);
                        retry--;
                        searchCache.ClearCache(".*", DateTime.Now);
                    }
                }

                if (canceled)
                {
                    return(false);
                }

                int count = CountResults(osr);
                if (totalCount == 0 && count == 0)
                {
                    LogInfo("No entries found");
                    DeleteFileStream(outputStream);
                    return(false);
                }

                if (canceled)
                {
                    return(false);
                }

                if (osr.Count > 0)
                {
                    // Transform the result
                    OutputResult(osr, outputStream);
                }
                else
                {
                    closeOutputStream = false;
                    DeleteFileStream(outputStream);
                }


                outputStarted = true;


                log.Debug(count + " entries found");
                if (count == 0)
                {
                    break;
                }
                int expectedCount = count;
                if (!string.IsNullOrEmpty(parameters["count"]) && int.TryParse(parameters["count"], out expectedCount) && count < expectedCount)
                {
                    break;
                }

                totalResults -= count;
                totalCount   += count;
                log.Debug(count + " entries found on " + totalResults + " requested");
                int paramCount;
                if (Int32.TryParse(parameters.Get("count"), out paramCount) && totalResults < paramCount)
                {
                    parameters.Set("count", "" + totalResults);
                }
                index += count;

                parameters.Set("startIndex", "" + index);

                if (closeOutputStream)
                {
                    outputStream.Close();
                }
            }

            return(totalCount > 0);  // success
        }
 public OpenSearchDescription GetOpenSearchDescription()
 {
     return(openSearchable.GetOpenSearchDescription());
 }