/// <summary>
        /// Retrieve objects of the predicates of the entity and store them to particular lists
        /// </summary>
        /// <param name="subjectIri">An IRI of the entity we are describing</param>
        /// <param name="language">The language of the search</param>
        /// <param name="endpoint">An endpoint where to search</param>
        /// <param name="count">If positive, set limit according to this value; if negative, retrieve all objects</param>
        public static Task RetrieveObjects(PredicateResultWrapperList predicateWrapperList, string subjectIri, string language, int count = -1)
        {
            Config.AssertAbsoluteUri(subjectIri);

            if (!predicateWrapperList.HasPredicates)
            {
                return(Task.CompletedTask);
            }
            SparqlParameterizedString template;

            if (count < 0)
            {
                template = QueryCreating.GetQueryTemplateCopy(QueryTemplates.SelectObjectsOfPredicate);
            }
            else
            {
                template = QueryCreating.GetQueryTemplateCopy(QueryTemplates.SelectObjectsOfPredicateWithLimit);
                template.SetLimit(count);
            }
            template.SetLanguage(language);
            template.SetSubject(subjectIri);
            List <Task> tasks = new List <Task>();

            foreach (var predicate in predicateWrapperList)
            {
                var task = RetrieveObjectsOfPredicate(predicate, template);
                tasks.Add(task);
            }
            return(Task.WhenAll(tasks));
            //var x = Parallel.ForEach(list, async predicate => await RetrieveObjectsOfPredicate(predicate, template, endpoint));
        }
        /// <summary>
        /// Get all the predicates from the triples with given subject IRI, sorted according to the popularity of predicates
        /// </summary>
        public static async Task RetrievePredicatesAndObjectCounts(PredicateResultWrapperList list, string subjectIri, string language, SparqlRemoteEndpoint endpoint)
        {
            Config.AssertAbsoluteUri(subjectIri);

            SparqlQuery query = QueryCreating.CreateQuery(QueryTemplates.SelectDistinctPredicateAndObjectCount, subjectIri, language);

            var holder = await RetrieveResultHolder(query, endpoint);

            foreach (var result in holder.QueryResultSet)
            {
                var predicate = await CreatePredicateNodeFromSparqlResult(subjectIri, holder.QueryEndpoint, result);

                list.InsertPredicateWrapper(predicate);
            }
            list.Sort();
        }
        /// <summary>
        /// Get all the predicates from the triples with given subject IRI from multiple endpoints, sorted according to the popularity of predicates
        /// </summary>
        public static async Task RetrievePredicatesAndObjectCounts(PredicateResultWrapperList list, string subjectIri, string language, List <SparqlRemoteEndpoint> endpoints)
        {
            Config.AssertAbsoluteUri(subjectIri);

            SparqlQuery query = QueryCreating.CreateQuery(QueryTemplates.SelectDistinctPredicateAndObjectCount, subjectIri, language);

            /*** create tasks ***/
            List <Task <ResultHolder> > tasks = new List <Task <ResultHolder> >(capacity: endpoints.Count);

            try
            {
                foreach (var endpoint in endpoints)
                {
                    tasks.Add(RetrieveResultHolder(query, endpoint));
                }
            }
            catch (Exception)
            {
                throw;
            }
            /*** process results ***/
            try
            {
                foreach (var task in tasks)
                {
                    var endpoint = task.Result.QueryEndpoint;
                    foreach (var result in task.Result.QueryResultSet)
                    {
                        var predicate = await CreatePredicateNodeFromSparqlResult(subjectIri, endpoint, result);

                        list.InsertPredicateWrapper(predicate);
                    }
                }
            }
            catch (AggregateException)
            {
                throw;
            }
            catch (Exception)
            {
                throw;
            }

            list.Sort();
            //TODO: handle duplicates
        }
        public async Task <ActionResult> EntityResultOnePredicate(OnePredicateInfo predicateInfo)
        {
            if (predicateInfo == null)
            {
                return(BadRequest());
            }
            ViewData[nameof(SearchInfo)] = predicateInfo;
            var queryResultWrappertList = new PredicateResultWrapperList();

            try
            {
                /*** validation ***/
                predicateInfo.Validate();

                /*** search preparation ***/
                SparqlRemoteEndpoint endpoint = SearchPreparing.CreateEndpoint(predicateInfo.Endpoints[0], predicateInfo.Timeout, predicateInfo.DefaultGraph);

                /*** preparing the predicate ***/
                queryResultWrappertList.InsertPredicateWrapper(predicateInfo.EntityIri, predicateInfo.PredicateIri, endpoint, predicateInfo.ExpectedObjects);

                /*** getting objects ***/
                await ResultRetrieving.RetrieveObjects(queryResultWrappertList, predicateInfo.EntityIri, predicateInfo.Language);

                //ViewData["ExecutionTime"] = query.QueryExecutionTime;
                ViewData[nameof(OnePredicateInfo.EntityIri)] = predicateInfo.EntityIri;
            }
            catch (BrowserException e)
            {
                return(View("QueryResultError", e.Message));
            }
            catch (InternalErrorException)
            {
                return(StatusCode(503));
            }
            catch (Exception)
            {
                //TODO: better text
                return(View("QueryResultError", "Unknown error..."));
            }

            return(View("EntityResultOnePredicate", queryResultWrappertList));
        }
        public async Task <ActionResult> EntityResultMultipleEndpoints(EntityInfo entityInfo)
        {
            if (entityInfo == null)
            {
                return(BadRequest());
            }
            var queryResultWrappertList = new PredicateResultWrapperList();

            try
            {
                /*** validation ***/
                entityInfo.Validate();
                ViewData[nameof(SearchInfo)] = entityInfo;

                /*** search preparation ***/
                List <SparqlRemoteEndpoint> endpoints = SearchPreparing.CreateEndpoints(entityInfo.Endpoints, entityInfo.Timeout);

                /*** getting all the predicates ***/
                await ResultRetrieving.RetrievePredicatesAndObjectCounts(queryResultWrappertList, entityInfo.EntityIri, entityInfo.Language, endpoints);

                queryResultWrappertList.ShortenToNthSubset(entityInfo.ResultsOnPage, entityInfo.PageNumber);

                /*** getting objects ***/
                await ResultRetrieving.RetrieveObjects(queryResultWrappertList, entityInfo.EntityIri, entityInfo.Language, entityInfo.MaxObjects);

                //ViewData["ExecutionTime"] = query.QueryExecutionTime;
                ViewData[nameof(EntityInfo.EntityIri)] = entityInfo.EntityIri;
            }
            catch (BrowserException e)
            {
                return(View("QueryResultError", e.Message));
            }
            catch (InternalErrorException)
            {
                return(StatusCode(503));
            }

            return(View("EntityResultOnlyFive", queryResultWrappertList));

            //return View("EntityResultMultipleEndpoints", queryResultWrappertList);
        }