Exemple #1
0
        public void StorageSesameDeleteTriples2()
        {
            Graph g = new Graph();

            g.BaseUri = new Uri("http://example.org/SesameTest/Delete2");
            g.NamespaceMap.AddNamespace("ex", new Uri("http://example.org/ns#"));
            g.Assert(g.CreateUriNode("ex:subj"), g.CreateUriNode("ex:pred"), g.CreateUriNode("ex:obj"));

            SesameHttpProtocolConnector sesame = SesameTests.GetConnection();

            sesame.SaveGraph(g);

            Console.WriteLine("Graph before deletion");
            TestTools.ShowGraph(g);

            //Delete the single triple
            sesame.UpdateGraph(g.BaseUri, null, g.Triples);

            Object results = sesame.Query("ASK WHERE { GRAPH <http://example.org/SesameTest/Delete2> { <http://example.org/ns#subj> ?p ?o } }");

            if (results is SparqlResultSet)
            {
                Assert.IsFalse(((SparqlResultSet)results).Result, "There should no longer be any triples present in the graph");
            }

            Graph h = new Graph();

            sesame.LoadGraph(h, g.BaseUri);

            Console.WriteLine("Graph after deletion");
            TestTools.ShowGraph(h);

            Assert.IsTrue(h.IsEmpty, "Graph should not be completely empty");
            Assert.IsFalse(g.Equals(h), "Graph retrieved should not be equal to original Graph");
        }
Exemple #2
0
        public void StorageSesameDeleteTriples1()
        {
            Graph g = new Graph();

            FileLoader.Load(g, "InferenceTest.ttl");
            g.BaseUri = new Uri("http://example.org/SesameTest");

            SesameHttpProtocolConnector sesame = SesameTests.GetConnection();

            sesame.SaveGraph(g);

            Console.WriteLine("Graph before deletion");
            TestTools.ShowGraph(g);

            //Delete all Triples about the Ford Fiesta
            sesame.UpdateGraph(g.BaseUri, null, g.GetTriplesWithSubject(new Uri("http://example.org/vehicles/FordFiesta")));

            Object results = sesame.Query("ASK WHERE { GRAPH <http://example.org/SesameTest> { <http://example.org/vehicles/FordFiesta> ?p ?o } }");

            if (results is SparqlResultSet)
            {
                Assert.IsFalse(((SparqlResultSet)results).Result, "There should no longer be any triples about the Ford Fiesta present");
            }

            Graph h = new Graph();

            sesame.LoadGraph(h, g.BaseUri);

            Console.WriteLine("Graph after deletion");
            TestTools.ShowGraph(h);

            Assert.IsFalse(h.IsEmpty, "Graph should not be completely empty");
            Assert.IsTrue(g.HasSubGraph(h), "Graph retrieved with missing Triples should be a sub-graph of the original Graph");
            Assert.IsFalse(g.Equals(h), "Graph retrieved should not be equal to original Graph");
        }
        public void StorageSesameDeleteTriples3()
        {
            SesameHttpProtocolConnector sesame = SesameTests.GetConnection();
            Graph g = new Graph();

            g.BaseUri = new Uri("http://example.org/sesame/chinese");
            FileLoader.Load(g, @"..\\resources\chinese.ttl");
            sesame.SaveGraph(g);

            String ask = "ASK WHERE { GRAPH <http://example.org/sesame/chinese> { ?s ?p '例子' } }";

            Object results = sesame.Query(ask);

            Assert.IsAssignableFrom <SparqlResultSet>(results);
            if (results is SparqlResultSet)
            {
                TestTools.ShowResults(results);
                Assert.True(((SparqlResultSet)results).Result);
            }

            // Now delete the triple in question
            sesame.UpdateGraph(g.BaseUri, null, g.Triples);

            // Re-issue ASK to check deletion
            results = sesame.Query(ask);
            Assert.IsAssignableFrom <SparqlResultSet>(results);
            if (results is SparqlResultSet)
            {
                TestTools.ShowResults(results);
                Assert.False(((SparqlResultSet)results).Result);
            }
        }
        public void StorageSesameDeleteTriples()
        {
            try
            {
                Graph g = new Graph();
                FileLoader.Load(g, "InferenceTest.ttl");
                g.BaseUri = new Uri("http://example.org/SesameTest");

                SesameHttpProtocolConnector sesame = new SesameHttpProtocolConnector("http://nottm-virtual.ecs.soton.ac.uk:8080/openrdf-sesame/", "unit-test");
                sesame.SaveGraph(g);

                Console.WriteLine("Graph before deletion");
                TestTools.ShowGraph(g);

                //Delete all Triples about the Ford Fiesta
                sesame.UpdateGraph(g.BaseUri, null, g.GetTriplesWithSubject(new Uri("http://example.org/vehicles/FordFiesta")));

                Object results = sesame.Query("ASK WHERE { <http://example.org/vehicles/FordFiesta> ?p ?o }");
                if (results is SparqlResultSet)
                {
                    Assert.IsFalse(((SparqlResultSet)results).Result, "There should no longer be any triples about the Ford Fiesta present");
                }

                Graph h = new Graph();
                sesame.LoadGraph(h, g.BaseUri);

                Console.WriteLine("Graph after deletion");
                TestTools.ShowGraph(h);

                Assert.IsFalse(h.IsEmpty, "Graph should not be completely empty");
                Assert.IsTrue(g.HasSubGraph(h), "Graph retrieved with missing Triples should be a sub-graph of the original Graph");
                Assert.IsFalse(g.Equals(h), "Graph retrieved should not be equal to original Graph");
            }
            catch (Exception ex)
            {
                TestTools.ReportError("Error", ex, true);
            }
        }
        /// <summary>
        /// Save new comment in RDF format
        /// </summary>
        /// <param name="comment"></param>
        /// <param name="update"></param>
        /// <returns>Guid url</returns>
        public string SaveComment(Comment comment, bool update = false)
        {
            using (SesameHttpProtocolConnector connector = new SesameHttpProtocolConnector(RtvSloConfig.RepositoryUrl, RtvSloConfig.RepositoryName))
            {
                if (connector.IsReady)
                {
                    /// SELECT ?guidUrl
                    /// WHERE {
                    ///     ?guidUrl rdf:type news:Comment
                    ///     ; news:ID "id"
                    /// }
                    string query = string.Format("SELECT ?guidUrl WHERE {{ ?guidUrl {0} {1} ; {2} \"{3}\" }}",
                                                                    Predicate.RdfType, Predicate.NewsComment, Predicate.NewsId, comment.Id.ToSafeString());

                    if (update)
                    {
                        /// SELECT ?guidUrl ?predicate ?object
                        /// WHERE {
                        ///     ?guidUrl rdf:type news:Comment
                        ///     ; news:ID "id"
                        ///     ; ?predicate ?object
                        /// }
                        query = string.Format("SELECT ?guidUrl ?predicate ?object WHERE {{ ?guidUrl {0} {1} ; {2} \"{3}\" ; ?predicate ?object }}",
                                                                    Predicate.RdfType, Predicate.NewsComment, Predicate.NewsId, comment.Id.ToSafeString());
                    }

                    SparqlResultSet queryResult = connector.QueryFormat(query);

                    string guidUrl = null;
                    INode guidUrlNode = null;
                    if (queryResult != null && !queryResult.Results.IsEmpty())
                    {
                        /// comment already exist
                        guidUrlNode = queryResult.Results.First().Value("guidUrl");
                        guidUrl = ((UriNode)guidUrlNode).Uri.AbsoluteUri;
                        if (!update)
                        {
                            return guidUrl;
                        }
                    }

                    /// save new or update
                    using (IGraph g = new Graph())
                    {
                        g.BaseUri = RepositoryHelper.BaseUrl.ToUri();
                        IList<Triple> newTriples = new List<Triple>();
                        IList<Triple> removeTriples = new List<Triple>();

                        if (string.IsNullOrEmpty(guidUrl))
                        {
                            update = false;
                            guidUrl = string.Format(RepositoryHelper.CommentUrlPattern, Guid.NewGuid().ToString());
                        }

                        INode subject = guidUrlNode != null ? guidUrlNode.CopyNode(g) : guidUrl.ToUriNode(g);
                        comment.RepositoryGuidUrl = guidUrl;

                        /// save new
                        if (!update)
                        {
                            /// initialize
                            newTriples.Add(new Triple(subject, Predicate.RdfType.ToUriNode(g), Predicate.NewsComment.ToUriNode(g)));

                            /// ID
                            newTriples.Add(new Triple(subject, Predicate.NewsId.ToUriNode(g),
                                comment.Id.ToString().ToLiteralNode(g, dataType: RepositoryHelper.IntegerDataType)));

                            /// see also
                            newTriples.Add(new Triple(subject, Predicate.RdfsSeeAlso.ToUriNode(g), comment.Url.ToUriNode(g)));

                            /// link with post
                            if (!string.IsNullOrEmpty(comment.PostGuidUrl))
                            {
                                newTriples.Add(new Triple(comment.PostGuidUrl.ToUriNode(g), Predicate.SiocHasReply.ToUriNode(g), subject));
                            }
                            else
                            {
                                this._logger.FatalFormat("RepositoryService, SaveComment, PostGuidUrl IS NULL - COMMENT: {0}", comment.Url);
                            }

                            /// has creator
                            if (!string.IsNullOrEmpty(comment.UserGuidUrl))
                            {
                                newTriples.Add(new Triple(subject, Predicate.SiocHasCreator.ToUriNode(g), comment.UserGuidUrl.ToUriNode(g)));
                            }
                            else
                            {
                                this._logger.FatalFormat("RepositoryService, SaveComment, UserGuidUrl IS NULL - COMMENT: {0}", comment.Url);
                            }
                        }

                        /// accessed date
                        newTriples.Add(new Triple(subject, Predicate.NewsAccessed.ToUriNode(g),
                            comment.AccessedDate.ToString(RepositoryHelper.DateTimeFormat).ToLiteralNode(g, dataType: RepositoryHelper.DateTimeDataType)));

                        /// content
                        newTriples.Add(new Triple(subject, Predicate.SiocContent.ToUriNode(g), comment.Content.ToLiteralNode(g)));

                        /// date created
                        newTriples.Add(new Triple(subject, Predicate.DctCreated.ToUriNode(g),
                            comment.DateCreated.Value.ToString(RepositoryHelper.DateTimeFormat).ToLiteralNode(g, dataType: RepositoryHelper.DateTimeDataType)));

                        /// rating
                        newTriples.Add(new Triple(subject, Predicate.MmcRating.ToUriNode(g),
                            comment.Rating.ToString().ToLiteralNode(g, dataType: RepositoryHelper.IntegerDataType)));

                        /// remove old triples
                        if (update)
                        {
                            this.RemoveTriples(removeTriples, queryResult, g, subject,
                                new string[] { Predicate.NewsAccessed, Predicate.SiocContent, Predicate.DctCreated, Predicate.MmcRating });
                        }

                        /// save
                        connector.UpdateGraph(g.BaseUri, newTriples, removeTriples);
                        return guidUrl;
                    }
                }
                else
                {
                    this._logger.FatalFormat("RepositoryService, SaveComment, SesameHttpProtocolConnector is not ready");
                }
            }

            return null;
        }
        /// <summary>
        /// Save post author to repository
        /// </summary>
        /// <param name="user"></param>
        /// <param name="update"></param>
        /// <returns></returns>
        public string SaveAuthor(User user, bool update = false)
        {
            using (SesameHttpProtocolConnector connector = new SesameHttpProtocolConnector(RtvSloConfig.RepositoryUrl, RtvSloConfig.RepositoryName))
            {
                if (connector.IsReady)
                {
                    /// SELECT ?guidUrl
                    /// WHERE {
                    ///     ?guidUrl rdf:type sioc:UserAccount
                    ///     ; news:nickname "name"
                    /// }
                    string query = string.Format("SELECT ?guidUrl WHERE {{ ?guidUrl {0} {1} ; {2} \"{3}\" }}",
                                                                    Predicate.RdfType, Predicate.SiocUserAccount, Predicate.NewsNickname, user.Name);

                    if (update)
                    {
                        /// SELECT ?guidUrl ?predicate ?object
                        /// WHERE {
                        ///     ?guidUrl rdf:type sioc:UserAccount
                        ///     ; news:nickname "name"
                        ///     ; ?predicate ?object
                        /// }
                        query = string.Format("SELECT ?guidUrl ?predicate ?object WHERE {{ ?guidUrl {0} {1} ; {2} \"{3}\" ; ?predicate ?object }}",
                                                                    Predicate.RdfType, Predicate.SiocUserAccount, Predicate.NewsNickname, user.Name);
                    }

                    SparqlResultSet queryResult = connector.QueryFormat(query);

                    string guidUrl = null;
                    INode guidUrlNode = null;
                    if (queryResult != null && !queryResult.Results.IsEmpty())
                    {
                        /// user already exist
                        guidUrlNode = queryResult.Results.First().Value("guidUrl");
                        guidUrl = ((UriNode)guidUrlNode).Uri.AbsoluteUri;
                        if (!update)
                        {
                            return guidUrl;
                        }
                    }

                    /// save new or update
                    using (IGraph g = new Graph())
                    {
                        g.BaseUri = RepositoryHelper.BaseUrl.ToUri();
                        IList<Triple> newTriples = new List<Triple>();
                        IList<Triple> removeTriples = new List<Triple>();

                        if (string.IsNullOrEmpty(guidUrl))
                        {
                            update = false;
                            guidUrl = string.Format(RepositoryHelper.UserUrlPattern, Guid.NewGuid().ToString());
                        }

                        INode subject = guidUrlNode != null ? guidUrlNode.CopyNode(g) : guidUrl.ToUriNode(g);
                        user.RepositoryGuidUrl = guidUrl;

                        if (!update)
                        {
                            /// initialize
                            newTriples.Add(new Triple(subject, Predicate.RdfType.ToUriNode(g), Predicate.SiocUserAccount.ToUriNode(g)));

                            /// user function
                            if (user.Function == UserFunctionEnum.Reader)
                            {
                                newTriples.Add(new Triple(subject, Predicate.SiocHasFunction.ToUriNode(g), RepositoryHelper.ReaderRoleUrl.ToUriNode(g)));
                            }
                            else if (user.Function == UserFunctionEnum.Journalist)
                            {
                                newTriples.Add(new Triple(subject, Predicate.SiocHasFunction.ToUriNode(g), RepositoryHelper.JournalistRoleUrl.ToUriNode(g)));
                            }
                        }

                        /// accessed date
                        newTriples.Add(new Triple(subject, Predicate.NewsAccessed.ToUriNode(g),
                            user.AccessedDate.ToString(RepositoryHelper.DateTimeFormat).ToLiteralNode(g, dataType: RepositoryHelper.DateTimeDataType)));

                        /// nickname
                        newTriples.Add(new Triple(subject, Predicate.NewsNickname.ToUriNode(g), user.Name.ToLiteralNode(g)));

                        /// remove old triples
                        if (update)
                        {
                            this.RemoveTriples(removeTriples, queryResult, g, subject,
                                new string[] { Predicate.NewsAccessed, Predicate.NewsNickname });
                        }

                        connector.UpdateGraph(g.BaseUri, newTriples, removeTriples);
                        return guidUrl;
                    }
                }
                else
                {
                    this._logger.FatalFormat("RepositoryService, SaveAuthor, SesameHttpProtocolConnector is not ready");
                }
            }

            return null;
        }
        /// <summary>
        /// Check if categories already exist in repository and save them if not
        /// </summary>
        /// <param name="category"></param>
        /// <returns>Child category repository url</returns>
        private string CheckAndSaveCategories(Category category)
        {
            using (SesameHttpProtocolConnector connector = new SesameHttpProtocolConnector(RtvSloConfig.RepositoryUrl, RtvSloConfig.RepositoryName))
            {
                if (connector.IsReady)
                {
                    Category tempCategory = category;
                    if (category.HasChild)
                    {
                        tempCategory = category.LastChild;
                    }

                    /// SELECT ?url
                    /// WHERE {
                    ///     ?url rdf:type sioc:Category .
                    ///     ?url rdfs:seeAlso <cat_url> .
                    /// }
                    string queryPattern = "SELECT ?url WHERE {{ ?url {0} {1} . ?url {2} <{3}> . }}";
                    SparqlResultSet result = connector.QueryFormat(queryPattern, Predicate.RdfType, Predicate.SiocCategory, Predicate.RdfsSeeAlso, tempCategory.Url);
                    if (result == null)
                    {
                        return null;
                    }
                    else if (!result.Results.IsEmpty())
                    {
                        /// child category already exists
                        return result.Results.First().Value("url").ToSafeString();
                    }

                    string categoryRepositoryUrl = null;

                    /// save category
                    using (IGraph g = new Graph())
                    {
                        g.BaseUri = RepositoryHelper.BaseUrl.ToUri();

                        IList<Triple> newTriples = new List<Triple>();

                        tempCategory = category;

                        bool topCategory = true;
                        do
                        {
                            /// fetch and check if category exists
                            result = connector.QueryFormat(queryPattern, Predicate.RdfType, Predicate.SiocCategory, Predicate.RdfsSeeAlso, tempCategory.Url);
                            if (result == null)
                            {
                                return null;
                            }
                            else if (result.Results.IsEmpty())
                            {

                                categoryRepositoryUrl = string.Format(RepositoryHelper.CategoryUrlPattern, tempCategory.Label);
                                INode subject = categoryRepositoryUrl.ToUriNode(g);

                                newTriples.Add(new Triple(subject, Predicate.RdfType.ToUriNode(g), Predicate.SiocCategory.ToUriNode(g)));
                                newTriples.Add(new Triple(subject, Predicate.RdfsSeeAlso.ToUriNode(g), tempCategory.Url.ToUriNode(g)));
                                newTriples.Add(new Triple(subject, Predicate.RdfsLabel.ToUriNode(g), tempCategory.Label.ToLiteralNode(g)));

                                if (!topCategory)
                                {
                                    INode parentObject = string.Format(RepositoryHelper.CategoryUrlPattern, tempCategory.Parent.Label).ToUriNode(g);
                                    newTriples.Add(new Triple(subject, Predicate.NewsSubCategoryOf.ToUriNode(g), parentObject));
                                }
                            }

                            topCategory = false;
                            tempCategory = tempCategory.NextChild;
                        }
                        while (tempCategory != null);

                        /// save new category
                        connector.UpdateGraph(g.BaseUri, newTriples, new List<Triple>());
                    }

                    return categoryRepositoryUrl;
                }
                else
                {
                    this._logger.FatalFormat("RepositoryService, CheckAndSaveCategories, SesameHttpProtocolConnector is not ready");
                }
            }

            return null;
        }
        /// <summary>
        /// Save new user
        /// </summary>
        /// <param name="user"></param>
        /// <param name="update"></param>
        /// <returns>User guid url</returns>
        public string SaveUser(User user, bool update = false)
        {
            using (SesameHttpProtocolConnector connector = new SesameHttpProtocolConnector(RtvSloConfig.RepositoryUrl, RtvSloConfig.RepositoryName))
            {
                if (connector.IsReady)
                {
                    /// SELECT ?guidUrl
                    /// WHERE {
                    ///     ?guidUrl rdf:type sioc:UserAccount
                    ///     ; news:ID "id"
                    /// }
                    string query = string.Format("SELECT ?guidUrl WHERE {{ ?guidUrl {0} {1} ; {2} \"{3}\" }}",
                                                Predicate.RdfType, Predicate.SiocUserAccount, Predicate.NewsId, user.Id);

                    if (update)
                    {
                        /// SELECT ?guidUrl ?predicate ?object
                        /// WHERE {
                        ///     ?guidUrl rdf:type sioc:UserAccount
                        ///     ; news:ID "id"
                        ///     ; ?predicate ?object
                        /// }
                        query = string.Format("SELECT ?guidUrl ?predicate ?object WHERE {{ ?guidUrl {0} {1} ; {2} \"{3}\" ; ?predicate ?object }}",
                                                Predicate.RdfType, Predicate.SiocUserAccount, Predicate.NewsId, user.Id);
                    }

                    SparqlResultSet queryResult = connector.QueryFormat(query);

                    string guidUrl = null;
                    UriNode guidUrlNode = null;
                    if (queryResult != null && !queryResult.Results.IsEmpty())
                    {
                        /// user already exist
                        guidUrlNode = queryResult.Results.First().Value("guidUrl") as UriNode;
                        guidUrl = guidUrlNode.Uri.AbsoluteUri;
                        if (!update)
                        {
                            return guidUrl;
                        }
                    }

                    /// save new or update
                    using (IGraph g = new Graph())
                    {
                        g.BaseUri = RepositoryHelper.BaseUrl.ToUri();
                        IList<Triple> newTriples = new List<Triple>();
                        IList<Triple> removeTriples = new List<Triple>();

                        if (string.IsNullOrEmpty(guidUrl))
                        {
                            update = false;
                            guidUrl = string.Format(RepositoryHelper.UserUrlPattern, Guid.NewGuid().ToString());
                        }
                        INode subject = guidUrlNode != null ? guidUrlNode.CopyNode(g) : guidUrl.ToUriNode(g);
                        user.RepositoryGuidUrl = guidUrl;

                        #region User

                        if (!update)
                        {
                            /// initialize
                            newTriples.Add(new Triple(subject, Predicate.RdfType.ToUriNode(g), Predicate.SiocUserAccount.ToUriNode(g)));

                            /// user function
                            if (user.Function == UserFunctionEnum.Reader)
                            {
                                newTriples.Add(new Triple(subject, Predicate.SiocHasFunction.ToUriNode(g), RepositoryHelper.ReaderRoleUrl.ToUriNode(g)));
                            }
                            else if (user.Function == UserFunctionEnum.Journalist)
                            {
                                newTriples.Add(new Triple(subject, Predicate.SiocHasFunction.ToUriNode(g), RepositoryHelper.JournalistRoleUrl.ToUriNode(g)));
                            }
                        }

                        /// accessed date
                        newTriples.Add(new Triple(subject, Predicate.NewsAccessed.ToUriNode(g),
                            user.AccessedDate.ToString(RepositoryHelper.DateTimeFormat).ToLiteralNode(g, dataType: RepositoryHelper.DateTimeDataType)));

                        /// ID
                        newTriples.Add(new Triple(subject, Predicate.NewsId.ToUriNode(g), user.Id.ToLiteralNode(g)));

                        /// Url
                        newTriples.Add(new Triple(subject, Predicate.RdfsSeeAlso.ToUriNode(g), user.Url.ToUriNode(g)));

                        /// gender
                        if (user.Gender == UserGenderEnum.Male)
                        {
                            newTriples.Add(new Triple(subject, Predicate.MmcHasGender.ToUriNode(g), RepositoryHelper.GenderMaleUrl.ToUriNode(g)));
                        }
                        else if (user.Gender == UserGenderEnum.Female)
                        {
                            newTriples.Add(new Triple(subject, Predicate.MmcHasGender.ToUriNode(g), RepositoryHelper.GenderFemaleUrl.ToUriNode(g)));
                        }

                        /// registered date
                        if (user.DateCreated.HasValue)
                        {
                            newTriples.Add(new Triple(subject, Predicate.DctCreated.ToUriNode(g),
                                user.DateCreated.Value.ToString(RepositoryHelper.DateFormat).ToLiteralNode(g)));
                        }

                        /// nickname
                        if (!string.IsNullOrEmpty(user.Name))
                        {
                            newTriples.Add(new Triple(subject, Predicate.NewsNickname.ToUriNode(g), user.Name.ToLiteralNode(g)));
                        }

                        /// email
                        if (!string.IsNullOrEmpty(user.Email))
                        {
                            newTriples.Add(new Triple(subject, Predicate.MmcEmail.ToUriNode(g), user.Email.ToLiteralNode(g)));
                        }

                        /// birthdate
                        if (user.Birthdate.HasValue)
                        {
                            newTriples.Add(new Triple(subject, Predicate.MmcBirthDate.ToUriNode(g),
                                user.Birthdate.Value.ToString(RepositoryHelper.DateFormat).ToLiteralNode(g, dataType: RepositoryHelper.DateDataType)));
                        }

                        /// about
                        if (!string.IsNullOrEmpty(user.Description))
                        {
                            newTriples.Add(new Triple(subject, Predicate.MmcAbout.ToUriNode(g), user.Description.ToLiteralNode(g)));
                        }

                        /// remove old triples
                        if (update)
                        {
                            this.RemoveTriples(removeTriples, queryResult, g, subject,
                                new string[] { Predicate.NewsAccessed, Predicate.NewsId, Predicate.RdfsSeeAlso, Predicate.MmcHasGender, Predicate.DctCreated,
                                                Predicate.NewsNickname, Predicate.MmcEmail, Predicate.MmcBirthDate, Predicate.MmcAbout });
                        }

                        #endregion User

                        #region UserStatistics

                        string statsGuid = Guid.NewGuid().ToString();
                        string statsGuidUrl = string.Format(RepositoryHelper.UserStatisticsUrlPattern, statsGuid);
                        UriNode statsGuidNode = null;

                        /// read existing statsGuidUrl
                        if (update)
                        {
                            statsGuidNode = queryResult.Results
                                .First(x => x.Value("predicate").ToSafeString() == Predicate.MmcUserStatistics.ToFullNamespaceUrl())
                                .Value("object") as UriNode;

                            statsGuidUrl = statsGuidNode.Uri.AbsoluteUri;

                            /// SELECT ?predicate ?object
                            /// WHERE {
                            ///     <guid> rdf:type mmc:Statistics
                            ///     ; ?predicate ?object
                            /// }

                            query = string.Format("SELECT ?predicate ?object WHERE {{ <{0}> {1} {2} ; ?predicate ?object }}",
                                        statsGuidUrl, Predicate.RdfType, Predicate.MmcStatistics);

                            queryResult = connector.QueryFormat(query);

                            if (queryResult == null || queryResult.Results.IsEmpty())
                            {
                                this._logger.FatalFormat("RepositoryService, SaveUser, Update statistics ERROR - QUERY: {0}", query);
                            }
                        }

                        INode statsSubject = statsGuidNode != null ? statsGuidNode.CopyNode(g) : statsGuidUrl.ToUriNode(g);

                        if(!update)
                        {
                            /// initialize
                            newTriples.Add(new Triple(statsSubject, Predicate.RdfType.ToUriNode(g), Predicate.MmcStatistics.ToUriNode(g)));
                            newTriples.Add(new Triple(subject, Predicate.MmcUserStatistics.ToUriNode(g), statsSubject));
                        }

                        /// rating
                        if (user.Rating > -1)
                        {
                            newTriples.Add(new Triple(statsSubject, Predicate.NewsAvgRating.ToUriNode(g),
                                user.Rating.ToString().ToLiteralNode(g, dataType: RepositoryHelper.DecimalDataType)));
                        }

                        /// num of ratings
                        if (user.NumOfRatings > -1)
                        {
                            newTriples.Add(new Triple(statsSubject, Predicate.NewsNRatings.ToUriNode(g),
                                user.NumOfRatings.ToString().ToLiteralNode(g, dataType: RepositoryHelper.IntegerDataType)));
                        }

                        /// num of forum posts
                        if (user.ForumPosts > -1)
                        {
                            newTriples.Add(new Triple(statsSubject, Predicate.MmcNumOfForumPosts.ToUriNode(g),
                                user.ForumPosts.ToString().ToLiteralNode(g, dataType: RepositoryHelper.IntegerDataType)));
                        }

                        /// num of blog posts
                        if (user.BlogPosts > -1)
                        {
                            newTriples.Add(new Triple(statsSubject, Predicate.MmcNumOfBlogPosts.ToUriNode(g),
                                user.BlogPosts.ToString().ToLiteralNode(g, dataType: RepositoryHelper.IntegerDataType)));
                        }

                        /// num of published pictures
                        if (user.ForumPosts > -1)
                        {
                            newTriples.Add(new Triple(statsSubject, Predicate.MmcNumOfPublishedPictures.ToUriNode(g),
                                user.PublishedPictures.ToString().ToLiteralNode(g, dataType: RepositoryHelper.IntegerDataType)));
                        }

                        /// num of published comments
                        if (user.PublishedComments > -1)
                        {
                            newTriples.Add(new Triple(statsSubject, Predicate.MmcNumOfPublishedComments.ToUriNode(g),
                                user.PublishedComments.ToString().ToLiteralNode(g, dataType: RepositoryHelper.IntegerDataType)));
                        }

                        /// num of published videos
                        if (user.PublishedVideos > -1)
                        {
                            newTriples.Add(new Triple(statsSubject, Predicate.MmcNumOfPublishedVideos.ToUriNode(g),
                                user.PublishedVideos.ToString().ToLiteralNode(g, dataType: RepositoryHelper.IntegerDataType)));
                        }

                        /// remove old triples
                        if (update)
                        {
                            this.RemoveTriples(removeTriples, queryResult, g, statsSubject,
                                new string[] { Predicate.NewsAvgRating, Predicate.NewsNRatings, Predicate.MmcNumOfForumPosts, Predicate.MmcNumOfBlogPosts,
                                        Predicate.MmcNumOfPublishedPictures, Predicate.MmcNumOfPublishedComments, Predicate.MmcNumOfPublishedVideos });
                        }

                        #endregion UserStatistics

                        connector.UpdateGraph(g.BaseUri, newTriples, removeTriples);
                        return guidUrl;
                    }
                }
                else
                {
                    this._logger.FatalFormat("RepositoryService, SaveUser, SesameHttpProtocolConnector is not ready");
                }
            }

            return null;
        }
        /// <summary>
        /// Save post details page in RDF format
        /// Updates post title
        /// </summary>
        /// <param name="post"></param>
        /// <param name="update"></param>
        /// <returns>Guid url</returns>
        public string SavePostDetails(Post post, bool update = false)
        {
            using (SesameHttpProtocolConnector connector = new SesameHttpProtocolConnector(RtvSloConfig.RepositoryUrl, RtvSloConfig.RepositoryName))
            {
                if (connector.IsReady)
                {
                    /// SELECT ?guidUrl ?predicate ?object
                    /// WHERE {
                    ///     ?guidUrl rdf:type sioc:Post
                    ///     ; news:ID "id"
                    ///     ; ?predicate ?object
                    /// }
                    string query = string.Format("SELECT ?guidUrl ?predicate ?object WHERE {{ ?guidUrl {0} {1} ; {2} \"{3}\" ; ?predicate ?object }}",
                                                            Predicate.RdfType, Predicate.SiocPost, Predicate.NewsId, post.Id.ToString(), Predicate.SiocTopic);
                    SparqlResultSet queryResult = connector.QueryFormat(query);

                    if (queryResult == null || queryResult.Results.IsEmpty())
                    {
                        this._logger.FatalFormat("RepositoryService, SavePostDetails, Query result has no results - QUERY: {0}", query);
                        return null; ;
                    }

                    /// save
                    using (IGraph g = new Graph())
                    {
                        g.BaseUri = RepositoryHelper.BaseUrl.ToUri();
                        IList<Triple> newTriples = new List<Triple>();
                        IList<Triple> removeTriples = new List<Triple>();

                        INode postGuid = queryResult.Results.First().Value("guidUrl").CopyNode(g);
                        post.RepositoryGuidUrl = ((UriNode)postGuid).Uri.AbsoluteUri;

                        #region Post Content

                        /// remove old title
                        this.RemoveTriples(removeTriples, queryResult, g, postGuid, new string[] { Predicate.DctTitle });

                        if (!update)
                        {
                            /// published at
                            newTriples.Add(new Triple(postGuid, Predicate.NewsPublishedAt.ToUriNode(g), RepositoryHelper.SiteUrl.ToUriNode(g)));
                        }

                        /// date created
                        newTriples.Add(new Triple(postGuid, Predicate.DctCreated.ToUriNode(g),
                            post.DateCreated.Value.ToString(RepositoryHelper.DateTimeFormat).ToLiteralNode(g, dataType: RepositoryHelper.DateTimeDataType)));

                        /// accessed date
                        newTriples.Add(new Triple(postGuid, Predicate.NewsAccessed.ToUriNode(g),
                            post.AccessedDate.ToString(RepositoryHelper.DateTimeFormat).ToLiteralNode(g, dataType: RepositoryHelper.DateTimeDataType)));

                        /// title
                        newTriples.Add(new Triple(postGuid, Predicate.DctTitle.ToUriNode(g), post.Title.ToLiteralNode(g)));

                        /// subtitle
                        if (!string.IsNullOrEmpty(post.Subtitle))
                        {
                            newTriples.Add(new Triple(postGuid, Predicate.MmcSubtitle.ToUriNode(g), post.Subtitle.ToLiteralNode(g)));
                        }

                        /// abstract
                        if (!string.IsNullOrEmpty(post.Abstract))
                        {
                            newTriples.Add(new Triple(postGuid, Predicate.DctAbstract.ToUriNode(g), post.Abstract.ToLiteralNode(g)));
                        }

                        /// last updated
                        newTriples.Add(new Triple(postGuid, Predicate.MmcLastUpdated.ToUriNode(g),
                            post.LastUpdated.ToString(RepositoryHelper.DateTimeFormat).ToLiteralNode(g, dataType: RepositoryHelper.DateTimeDataType)));

                        /// location
                        if (!string.IsNullOrEmpty(post.Location))
                        {
                            newTriples.Add(new Triple(postGuid, Predicate.NewsLocation.ToUriNode(g),
                                post.Location.ToLiteralNode(g, language: RepositoryHelper.LanguageEnglish))); /// hack to get posts from region
                        }

                        /// content
                        if (!string.IsNullOrEmpty(post.Content))
                        {
                            newTriples.Add(new Triple(postGuid, Predicate.SiocContent.ToUriNode(g), post.Content.ToLiteralNode(g)));
                        }

                        /// authors
                        if (!post.Authors.IsEmpty())
                        {
                            foreach (User author in post.Authors)
                            {
                                if (!string.IsNullOrEmpty(author.RepositoryGuidUrl))
                                {
                                    newTriples.Add(new Triple(postGuid, Predicate.SiocHasCreator.ToUriNode(g), author.RepositoryGuidUrl.ToUriNode(g)));
                                }
                            }
                        }

                        if (update)
                        {
                            /// remove old triples
                            this.RemoveTriples(removeTriples, queryResult, g, postGuid,
                                new string[]{ Predicate.DctCreated, Predicate.NewsAccessed, Predicate.MmcSubtitle, Predicate.DctAbstract, Predicate.MmcLastUpdated,
                                   Predicate.NewsLocation, Predicate.SiocContent, Predicate.SiocHasCreator });
                        }

                        #endregion Post Content

                        #region Statistics

                        string statsGuid = Guid.NewGuid().ToString();
                        string statsGuidUrl = string.Format(RepositoryHelper.StatisticsUrlPattern, statsGuid);
                        UriNode statsGuidNode = null;

                        /// read existing statsGuidUrl
                        if (update)
                        {
                            statsGuidNode = queryResult.Results
                                .First(x => x.Value("predicate").ToSafeString() == Predicate.NewsStatistics.ToFullNamespaceUrl())
                                .Value("object") as UriNode;

                            statsGuidUrl = statsGuidNode.Uri.AbsoluteUri;

                            /// SELECT ?predicate ?object
                            /// WHERE {
                            ///     <guid> rdf:type news:Stat
                            ///     ; ?predicate ?object
                            /// }
                            query = string.Format("SELECT ?predicate ?object WHERE {{ <{0}> {1} {2} ; ?predicate ?object }}",
                                        statsGuidUrl, Predicate.RdfType, Predicate.NewsStat);

                            queryResult = connector.QueryFormat(query);

                            if (queryResult == null || queryResult.Results.IsEmpty())
                            {
                                this._logger.FatalFormat("RepositoryService, SavePostDetails, Update statistics ERROR - QUERY: {0}", query);
                            }
                        }

                        INode statsSubject = statsGuidNode != null ? statsGuidNode.CopyNode(g) : statsGuidUrl.ToUriNode(g);
                        if (!update)
                        {
                            /// initialize
                            newTriples.Add(new Triple(statsSubject, Predicate.RdfType.ToUriNode(g), Predicate.NewsStat.ToUriNode(g)));
                            newTriples.Add(new Triple(postGuid, Predicate.NewsStatistics.ToUriNode(g), statsSubject));
                        }

                        /// number of comments
                        if (post.NumOfComments > -1)
                        {
                            newTriples.Add(new Triple(statsSubject, Predicate.NewsNComments.ToUriNode(g),
                                post.NumOfComments.ToString().ToLiteralNode(g, dataType: RepositoryHelper.IntegerDataType)));
                        }

                        /// avgerage rating
                        if (post.AvgRating > -1)
                        {
                            newTriples.Add(new Triple(statsSubject, Predicate.NewsAvgRating.ToUriNode(g),
                                post.AvgRating.ToString().ToLiteralNode(g, dataType: RepositoryHelper.DecimalDataType)));
                        }

                        /// number of ratings
                        if (post.NumOfRatings > -1)
                        {
                            newTriples.Add(new Triple(statsSubject, Predicate.NewsNRatings.ToUriNode(g),
                                post.NumOfRatings.ToString().ToLiteralNode(g, dataType: RepositoryHelper.IntegerDataType)));
                        }

                        /// number of FB likes
                        if (post.NumOfFbLikes > -1)
                        {
                            newTriples.Add(new Triple(statsSubject, Predicate.NewsNFBLikes.ToUriNode(g),
                                post.NumOfFbLikes.ToString().ToLiteralNode(g, dataType: RepositoryHelper.IntegerDataType)));
                        }

                        /// number of tweets
                        if (post.NumOfTweets > -1)
                        {
                            newTriples.Add(new Triple(statsSubject, Predicate.NewsNTweets.ToUriNode(g),
                                post.NumOfTweets.ToString().ToLiteralNode(g, dataType: RepositoryHelper.IntegerDataType)));
                        }

                        if (update)
                        {
                            /// remove old triples
                            this.RemoveTriples(removeTriples, queryResult, g, statsSubject,
                                new string[] { Predicate.NewsNComments, Predicate.NewsAvgRating, Predicate.NewsNRatings, Predicate.NewsNFBLikes, Predicate.NewsNTweets });
                        }

                        #endregion Statistics

                        connector.UpdateGraph(g.BaseUri, newTriples, removeTriples);
                        return post.RepositoryGuidUrl;
                    }
                }
                else
                {
                    this._logger.FatalFormat("RepositoryService, SavePostDetails, SesameHttpProtocolConnector is not ready");
                }
            }

            return null;
        }
        /// <summary>
        /// Save only post data scraped from archive page in RDF format if don't already exist
        /// ID, Title, Url, Category
        /// </summary>
        /// <param name="post"></param>
        /// <returns>Guid url</returns>
        public string SaveOrUpdatePostOverview(Post post)
        {
            /// save category
            string categoryUrl = this.CheckAndSaveCategories(post.Category);

            using (SesameHttpProtocolConnector connector = new SesameHttpProtocolConnector(RtvSloConfig.RepositoryUrl, RtvSloConfig.RepositoryName))
            {
                if (connector.IsReady)
                {
                    /// SELECT ?guidUrl ?predicate ?object
                    /// WHERE {
                    ///     ?guidUrl rdf:type sioc:Post
                    ///     ; news:ID "id"
                    ///     ; ?predicate ?object
                    /// }
                    SparqlResultSet queryResult = connector.QueryFormat("SELECT ?guidUrl ?predicate ?object WHERE {{ ?guidUrl {0} {1} ; {2} \"{3}\" ; ?predicate ?object }}",
                                                            Predicate.RdfType, Predicate.SiocPost, Predicate.NewsId, post.Id.ToString(), Predicate.SiocTopic);
                    /// update existing
                    if (queryResult != null && !queryResult.Results.IsEmpty())
                    {
                        using (IGraph g = new Graph())
                        {
                            g.BaseUri = RepositoryHelper.BaseUrl.ToUri();
                            IList<Triple> newTriples = new List<Triple>();

                            INode postGuid = queryResult.Results.First().Value("guidUrl").CopyNode(g);
                            post.RepositoryGuidUrl = ((UriNode)postGuid).Uri.AbsoluteUri;

                            /// select categories
                            IEnumerable<SparqlResult> categories = queryResult.Results
                                .Where(x => x.Value("predicate").ToSafeString() == Predicate.SiocTopic.ToFullNamespaceUrl());

                            SparqlResult categoryResult = categories.FirstOrDefault(x => x.Value("object").ToSafeString() == categoryUrl);
                            if (categoryResult == null)
                            {
                                newTriples.Add(new Triple(postGuid, Predicate.SiocTopic.ToUriNode(g), categoryUrl.ToUriNode(g)));
                            }

                            /// select url
                            IEnumerable<SparqlResult> postUrls = queryResult.Results
                                .Where(x => x.Value("predicate").ToSafeString() == Predicate.RdfsSeeAlso.ToFullNamespaceUrl());

                            SparqlResult postUrlResult = postUrls.FirstOrDefault(x => x.Value("object").ToSafeString() == post.Url);
                            if (postUrlResult == null)
                            {
                                newTriples.Add(new Triple(postGuid, Predicate.RdfsSeeAlso.ToUriNode(g), post.Url.ToUriNode(g)));
                            }

                            connector.UpdateGraph(g.BaseUri, newTriples, new List<Triple>());
                        }
                    }
                    /// save new
                    else
                    {
                        using (IGraph g = new Graph())
                        {
                            g.BaseUri = RepositoryHelper.BaseUrl.ToUri();
                            IList<Triple> newTriples = new List<Triple>();

                            string guidUrl = string.Format(RepositoryHelper.PostUrlPattern, Guid.NewGuid().ToString());
                            INode guidNode = guidUrl.ToUriNode(g);
                            post.RepositoryGuidUrl = guidUrl;

                            /// define post
                            newTriples.Add(new Triple(guidNode, Predicate.RdfType.ToUriNode(g), Predicate.SiocPost.ToUriNode(g)));
                            /// ID
                            newTriples.Add(new Triple(guidNode, Predicate.NewsId.ToUriNode(g),
                                post.Id.ToString().ToLiteralNode(g, dataType: RepositoryHelper.IntegerDataType)));
                            /// title
                            newTriples.Add(new Triple(guidNode, Predicate.DctTitle.ToUriNode(g), post.Title.ToLiteralNode(g)));
                            /// post url
                            newTriples.Add(new Triple(guidNode, Predicate.RdfsSeeAlso.ToUriNode(g), post.Url.ToUriNode(g)));

                            /// category
                            if (!string.IsNullOrEmpty(categoryUrl))
                            {
                                newTriples.Add(new Triple(guidNode, Predicate.SiocTopic.ToUriNode(g), categoryUrl.ToUriNode(g)));
                            }

                            connector.UpdateGraph(g.BaseUri, newTriples, new List<Triple>());
                        }
                    }

                    return post.RepositoryGuidUrl;
                }
                else
                {
                    this._logger.FatalFormat("RepositoryService, SavePostOverview, SesameHttpProtocolConnector is not ready");
                }
            }

            return null;
        }