Beispiel #1
0
        /// <summary>
        /// Evaluates the Command in the given Context.
        /// </summary>
        /// <param name="context">Evaluation Context.</param>
        public override void Evaluate(SparqlUpdateEvaluationContext context)
        {
            bool datasetOk  = false;
            bool defGraphOk = false;

            try
            {
                // First evaluate the WHERE pattern to get the affected bindings
                ISparqlAlgebra where = _wherePattern.ToAlgebra();
                if (context.Commands != null)
                {
                    where = context.Commands.ApplyAlgebraOptimisers(where);
                }

                // Set Active Graph for the WHERE
                // Don't bother if there are USING URIs as these would override any Active Graph we set here
                // so we can save ourselves the effort of doing this
                if (!UsingUris.Any())
                {
                    if (_graphUri != null)
                    {
                        context.Data.SetActiveGraph(_graphUri);
                        defGraphOk = true;
                    }
                    else
                    {
                        context.Data.SetActiveGraph((Uri)null);
                        defGraphOk = true;
                    }
                }

                // We need to make a dummy SparqlQuery object since if the Command has used any
                // USING NAMEDs along with GRAPH clauses then the algebra needs to have the
                // URIs available to it which it gets from the Query property of the Context
                // object
                SparqlQuery query = new SparqlQuery();
                foreach (Uri u in UsingUris)
                {
                    query.AddDefaultGraph(u);
                }
                foreach (Uri u in UsingNamedUris)
                {
                    query.AddNamedGraph(u);
                }
                SparqlEvaluationContext queryContext = new SparqlEvaluationContext(query, context.Data, context.QueryProcessor);
                if (UsingUris.Any())
                {
                    // If there are USING URIs set the Active Graph to be formed of the Graphs with those URIs
                    context.Data.SetActiveGraph(_usingUris);
                    datasetOk = true;
                }
                BaseMultiset results = queryContext.Evaluate(where);
                if (results is IdentityMultiset)
                {
                    results = new SingletonMultiset(results.Variables);
                }
                if (UsingUris.Any())
                {
                    // If there are USING URIs reset the Active Graph afterwards
                    // Also flag the dataset as no longer being OK as this flag is used in the finally
                    // block to determine whether the Active Graph needs resetting which it may do if the
                    // evaluation of the
                    context.Data.ResetActiveGraph();
                    datasetOk = false;
                }

                // Reset Active Graph for the WHERE
                if (defGraphOk)
                {
                    context.Data.ResetActiveGraph();
                    defGraphOk = false;
                }

                // Get the Graph to which we are deleting and inserting
                IGraph g;
                bool   newGraph = false;
                if (context.Data.HasGraph(_graphUri))
                {
                    g = context.Data.GetModifiableGraph(_graphUri);
                }
                else
                {
                    // Inserting into a new graph. This will raise an exception if the dataset is immutable
                    context.Data.AddGraph(new Graph {
                        BaseUri = _graphUri
                    });
                    g        = context.Data.GetModifiableGraph(_graphUri);
                    newGraph = true;
                }

                // Delete the Triples for each Solution
                List <Triple> deletedTriples = new List <Triple>();
                foreach (ISet s in results.Sets)
                {
                    try
                    {
                        // If the Default Graph is non-existent then Deletions have no effect on it
                        if (g != null)
                        {
                            ConstructContext constructContext = new ConstructContext(g, s, true);
                            foreach (IConstructTriplePattern p in _deletePattern.TriplePatterns.OfType <IConstructTriplePattern>())
                            {
                                try
                                {
                                    deletedTriples.Add(p.Construct(constructContext));
                                }
                                catch (RdfQueryException)
                                {
                                    // If we get an error here then we couldn't construct a specific
                                    // triple so we continue anyway
                                }
                            }
                            g.Retract(deletedTriples);
                        }
                    }
                    catch (RdfQueryException)
                    {
                        // If we get an error here this means we couldn't construct for this solution so the
                        // solution is ignored for this graph
                    }

                    // Triples from GRAPH clauses
                    foreach (GraphPattern gp in _deletePattern.ChildGraphPatterns)
                    {
                        deletedTriples.Clear();
                        try
                        {
                            String graphUri;
                            switch (gp.GraphSpecifier.TokenType)
                            {
                            case Token.URI:
                                graphUri = gp.GraphSpecifier.Value;
                                break;

                            case Token.VARIABLE:
                                String graphVar = gp.GraphSpecifier.Value.Substring(1);
                                if (s.ContainsVariable(graphVar))
                                {
                                    INode temp = s[graphVar];
                                    if (temp == null)
                                    {
                                        // If the Variable is not bound then skip
                                        continue;
                                    }
                                    else if (temp.NodeType == NodeType.Uri)
                                    {
                                        graphUri = temp.ToSafeString();
                                    }
                                    else
                                    {
                                        // If the Variable is not bound to a URI then skip
                                        continue;
                                    }
                                }
                                else
                                {
                                    // If the Variable is not bound for this solution then skip
                                    continue;
                                }
                                break;

                            default:
                                // Any other Graph Specifier we have to ignore this solution
                                continue;
                            }

                            // If the Dataset doesn't contain the Graph then no need to do the Deletions
                            if (!context.Data.HasGraph(UriFactory.Create(graphUri)))
                            {
                                continue;
                            }

                            // Do the actual Deletions
                            IGraph           h = context.Data.GetModifiableGraph(UriFactory.Create(graphUri));
                            ConstructContext constructContext = new ConstructContext(h, s, true);
                            foreach (IConstructTriplePattern p in gp.TriplePatterns.OfType <IConstructTriplePattern>())
                            {
                                try
                                {
                                    deletedTriples.Add(p.Construct(constructContext));
                                }
                                catch (RdfQueryException)
                                {
                                    // If we get an error here then we couldn't construct a specific triple
                                    // so we continue anyway
                                }
                            }
                            h.Retract(deletedTriples);
                        }
                        catch (RdfQueryException)
                        {
                            // If we get an error here this means we couldn't construct for this solution so the
                            // solution is ignore for this graph
                        }
                    }
                }

                // Insert the Triples for each Solution
                foreach (ISet s in results.Sets)
                {
                    List <Triple> insertedTriples = new List <Triple>();
                    try
                    {
                        ConstructContext constructContext = new ConstructContext(g, s, true);
                        foreach (IConstructTriplePattern p in _insertPattern.TriplePatterns.OfType <IConstructTriplePattern>())
                        {
                            try
                            {
                                insertedTriples.Add(p.Construct(constructContext));
                            }
                            catch (RdfQueryException)
                            {
                                // If we get an error here then we couldn't construct a specific triple
                                // so we continue anyway
                            }
                        }
                        g.Assert(insertedTriples.Select(t => t.IsGroundTriple ? t : t.CopyTriple(g)));
                    }
                    catch (RdfQueryException)
                    {
                        // If we get an error here this means we couldn't construct for this solution so the
                        // solution is ignored for this graph
                    }

                    if (insertedTriples.Count == 0 && newGraph && _graphUri != null)
                    {
                        // Remove the named graph we added as we did not insert any triples
                        context.Data.RemoveGraph(_graphUri);
                    }

                    // Triples from GRAPH clauses
                    foreach (GraphPattern gp in _insertPattern.ChildGraphPatterns)
                    {
                        insertedTriples.Clear();
                        try
                        {
                            String graphUri;
                            switch (gp.GraphSpecifier.TokenType)
                            {
                            case Token.URI:
                                graphUri = gp.GraphSpecifier.Value;
                                break;

                            case Token.VARIABLE:
                                String graphVar = gp.GraphSpecifier.Value.Substring(1);
                                if (s.ContainsVariable(graphVar))
                                {
                                    INode temp = s[graphVar];
                                    if (temp == null)
                                    {
                                        // If the Variable is not bound then skip
                                        continue;
                                    }
                                    else if (temp.NodeType == NodeType.Uri)
                                    {
                                        graphUri = temp.ToSafeString();
                                    }
                                    else
                                    {
                                        // If the Variable is not bound to a URI then skip
                                        continue;
                                    }
                                }
                                else
                                {
                                    // If the Variable is not bound for this solution then skip
                                    continue;
                                }
                                break;

                            default:
                                // Any other Graph Specifier we have to ignore this solution
                                continue;
                            }

                            // Ensure the Graph we're inserting to exists in the dataset creating it if necessary
                            IGraph h;
                            Uri    destUri = UriFactory.Create(graphUri);
                            if (context.Data.HasGraph(destUri))
                            {
                                h = context.Data.GetModifiableGraph(destUri);
                            }
                            else
                            {
                                h         = new Graph();
                                h.BaseUri = destUri;
                                context.Data.AddGraph(h);
                                h = context.Data.GetModifiableGraph(destUri);
                            }

                            // Do the actual Insertions
                            ConstructContext constructContext = new ConstructContext(h, s, true);
                            foreach (IConstructTriplePattern p in gp.TriplePatterns.OfType <IConstructTriplePattern>())
                            {
                                try
                                {
                                    Triple t = p.Construct(constructContext);
                                    t = new Triple(t.Subject, t.Predicate, t.Object, destUri);
                                    insertedTriples.Add(t);
                                }
                                catch (RdfQueryException)
                                {
                                    // If we get an error here this means we couldn't construct a specific
                                    // triple so we continue anyway
                                }
                            }
                            h.Assert(insertedTriples.Select(t => t.IsGroundTriple ? t : t.CopyTriple(h)));
                        }
                        catch (RdfQueryException)
                        {
                            // If we get an error here this means we couldn't construct for this solution so the
                            // solution is ignored for this graph
                        }
                    }
                }
            }
            finally
            {
                // If the Dataset was set and an error occurred in doing the WHERE clause then
                // we'll need to Reset the Active Graph
                if (datasetOk)
                {
                    context.Data.ResetActiveGraph();
                }
                if (defGraphOk)
                {
                    context.Data.ResetActiveGraph();
                }
            }
        }
        /// <summary>
        /// Evaluates the Command in the given Context
        /// </summary>
        /// <param name="context">Evaluation Context</param>
        public override void Evaluate(SparqlUpdateEvaluationContext context)
        {
            bool datasetOk  = false;
            bool defGraphOk = false;

            try
            {
                // First evaluate the WHERE pattern to get the affected bindings
                ISparqlAlgebra where = _wherePattern.ToAlgebra();
                if (context.Commands != null)
                {
                    where = context.Commands.ApplyAlgebraOptimisers(where);
                }

                // Set Active Graph for the WHERE
                // Don't bother if there are USING URIs as these would override any Active Graph we set here
                // so we can save ourselves the effort of doing this
                if (!UsingUris.Any())
                {
                    if (_graphUri != null)
                    {
                        context.Data.SetActiveGraph(_graphUri);
                        defGraphOk = true;
                    }
                    else
                    {
                        context.Data.SetActiveGraph((Uri)null);
                        defGraphOk = true;
                    }
                }

                // We need to make a dummy SparqlQuery object since if the Command has used any
                // USING NAMEDs along with GRAPH clauses then the algebra needs to have the
                // URIs available to it which it gets from the Query property of the Context
                // object
                SparqlQuery query = new SparqlQuery();
                foreach (Uri u in UsingUris)
                {
                    query.AddDefaultGraph(u);
                }
                foreach (Uri u in UsingNamedUris)
                {
                    query.AddNamedGraph(u);
                }
                SparqlEvaluationContext queryContext = new SparqlEvaluationContext(query, context.Data, context.QueryProcessor);
                if (UsingUris.Any())
                {
                    // If there are USING URIs set the Active Graph to be formed of the Graphs with those URIs
                    context.Data.SetActiveGraph(_usingUris);
                    datasetOk = true;
                }
                BaseMultiset results = queryContext.Evaluate(where);
                if (results is IdentityMultiset)
                {
                    results = new SingletonMultiset(results.Variables);
                }
                if (UsingUris.Any())
                {
                    // If there are USING URIs reset the Active Graph afterwards
                    // Also flag the dataset as no longer being OK as this flag is used in the finally
                    // block to determine whether the Active Graph needs resetting which it may do if the
                    // evaluation of the query fails for any reason
                    context.Data.ResetActiveGraph();
                    datasetOk = false;
                }

                // Reset Active Graph for the WHERE
                if (defGraphOk)
                {
                    context.Data.ResetActiveGraph();
                    defGraphOk = false;
                }

                // TODO: Need to detect when we create a Graph for Insertion but then fail to insert anything since in this case the Inserted Graph should be removed

                // Get the Graph to which we are inserting Triples with no explicit Graph clause
                IGraph g = null;
                if (_insertPattern.TriplePatterns.Count > 0)
                {
                    if (context.Data.HasGraph(_graphUri))
                    {
                        g = context.Data.GetModifiableGraph(_graphUri);
                    }
                    else
                    {
                        // insertedGraphs.Add(this._graphUri);
                        g         = new Graph();
                        g.BaseUri = _graphUri;
                        context.Data.AddGraph(g);
                        g = context.Data.GetModifiableGraph(_graphUri);
                    }
                }

                // Keep a record of graphs to which we insert
                MultiDictionary <Uri, IGraph> graphs = new MultiDictionary <Uri, IGraph>(u => (u != null ? u.GetEnhancedHashCode() : 0), true, new UriComparer(), MultiDictionaryMode.AVL);

                // Insert the Triples for each Solution
                foreach (ISet s in results.Sets)
                {
                    List <Triple> insertedTriples = new List <Triple>();

                    try
                    {
                        // Create a new Construct Context for each Solution
                        ConstructContext constructContext = new ConstructContext(null, s, true);

                        // Triples from raw Triple Patterns
                        if (_insertPattern.TriplePatterns.Count > 0)
                        {
                            foreach (IConstructTriplePattern p in _insertPattern.TriplePatterns.OfType <IConstructTriplePattern>())
                            {
                                try
                                {
                                    insertedTriples.Add(p.Construct(constructContext));
                                }
                                catch (RdfQueryException)
                                {
                                    // If we throw an error this means we couldn't construct a specific Triple
                                    // so we continue anyway
                                }
                            }
                            g.Assert(insertedTriples);
                        }

                        // Triples from GRAPH clauses
                        foreach (GraphPattern gp in _insertPattern.ChildGraphPatterns)
                        {
                            insertedTriples.Clear();
                            try
                            {
                                String graphUri;
                                switch (gp.GraphSpecifier.TokenType)
                                {
                                case Token.URI:
                                    graphUri = gp.GraphSpecifier.Value;
                                    break;

                                case Token.VARIABLE:
                                    String graphVar = gp.GraphSpecifier.Value.Substring(1);
                                    if (s.ContainsVariable(graphVar))
                                    {
                                        INode temp = s[graphVar];
                                        if (temp == null)
                                        {
                                            // If the Variable is not bound then skip
                                            continue;
                                        }
                                        if (temp.NodeType == NodeType.Uri)
                                        {
                                            graphUri = temp.ToSafeString();
                                        }
                                        else
                                        {
                                            // If the Variable is not bound to a URI then skip
                                            continue;
                                        }
                                    }
                                    else
                                    {
                                        // If the Variable is not bound for this solution then skip
                                        continue;
                                    }
                                    break;

                                default:
                                    // Any other Graph Specifier we have to ignore this solution
                                    continue;
                                }

                                // Ensure the Graph we're inserting to exists in the dataset creating it if necessary
                                IGraph h;
                                Uri    destUri = UriFactory.Create(graphUri);
                                if (graphs.ContainsKey(destUri))
                                {
                                    h = graphs[destUri];
                                }
                                else
                                {
                                    if (context.Data.HasGraph(destUri))
                                    {
                                        h = context.Data.GetModifiableGraph(destUri);
                                    }
                                    else
                                    {
                                        // insertedGraphs.Add(destUri);
                                        h         = new Graph();
                                        h.BaseUri = destUri;
                                        context.Data.AddGraph(h);
                                        h = context.Data.GetModifiableGraph(destUri);
                                    }
                                    graphs.Add(destUri, h);
                                }

                                // Do the actual Insertions
                                foreach (IConstructTriplePattern p in gp.TriplePatterns.OfType <IConstructTriplePattern>())
                                {
                                    try
                                    {
                                        Triple t = p.Construct(constructContext);
                                        t = new Triple(t.Subject, t.Predicate, t.Object, destUri);
                                        insertedTriples.Add(t);
                                    }
                                    catch (RdfQueryException)
                                    {
                                        // If we throw an error this means we couldn't construct a specific Triple
                                        // so we continue anyway
                                    }
                                }
                                h.Assert(insertedTriples);
                            }
                            catch (RdfQueryException)
                            {
                                // If we throw an error this means we couldn't construct for this solution so the
                                // solution is ignored for this Graph
                            }
                        }
                    }
                    catch (RdfQueryException)
                    {
                        // If we throw an error this means we couldn't construct for this solution so the
                        // solution is ignored for this graph
                    }
                }
            }
            finally
            {
                // If the Dataset was set and an error occurred in doing the WHERE clause then
                // we'll need to Reset the Active Graph
                if (datasetOk)
                {
                    context.Data.ResetActiveGraph();
                }
                if (defGraphOk)
                {
                    context.Data.ResetActiveGraph();
                }
            }
        }