/// <summary>
 /// Constructs a Node based on this Pattern for the given Set
 /// </summary>
 /// <param name="context">Construct Context</param>
 /// <returns></returns>
 protected internal abstract INode Construct(ConstructContext context);
Exemple #2
0
        /// <summary>
        /// Evaluates the Command in the given Context
        /// </summary>
        /// <param name="context">Evaluation Context</param>
        public override void Evaluate(SparqlUpdateEvaluationContext context)
        {
            //Split the Pattern into the set of Graph Patterns
            List<GraphPattern> patterns = new List<GraphPattern>();
            if (this._pattern.IsGraph)
            {
                patterns.Add(this._pattern);
            }
            else if (this._pattern.TriplePatterns.Count > 0 || this._pattern.HasChildGraphPatterns)
            {
                if (this._pattern.TriplePatterns.Count > 0)
                {
                    patterns.Add(new GraphPattern());
                    this._pattern.TriplePatterns.ForEach(tp => patterns[0].AddTriplePattern(tp));
                }
                this._pattern.ChildGraphPatterns.ForEach(gp => patterns.Add(gp));
            }
            else
            {
                //If no Triple Patterns and No Child Graph Patterns nothing to do
                return;
            }

            foreach (GraphPattern pattern in patterns)
            {
                if (!this.IsValidDataPattern(pattern, false)) throw new SparqlUpdateException("Cannot evaluate a INSERT DATA command where any of the Triple Patterns are not concrete triples (variables are not permitted) or any of the GRAPH clauses have nested Graph Patterns");

                //Get the Target Graph
                IGraph target;
                Uri graphUri;
                if (pattern.IsGraph)
                {
                    switch (pattern.GraphSpecifier.TokenType)
                    {
                        case Token.QNAME:
                            throw new NotSupportedException("Graph Specifiers as QNames for INSERT DATA Commands are not supported - please specify an absolute URI instead");
                        case Token.URI:
                            graphUri = UriFactory.Create(pattern.GraphSpecifier.Value);
                            break;
                        default:
                            throw new SparqlUpdateException("Cannot evaluate an INSERT DATA Command as the Graph Specifier is not a QName/URI");
                    }
                }
                else
                {
                    graphUri = null;
                }
                if (context.Data.HasGraph(graphUri))
                {
                    target = context.Data.GetModifiableGraph(graphUri);
                }
                else
                {
                    //If the Graph does not exist then it must be created
                    target = new Graph();
                    target.BaseUri = graphUri;
                    context.Data.AddGraph(target);
                }

                //Insert the actual Triples
                INode subj, pred, obj;
                ConstructContext constructContext = new ConstructContext(target, null, true);
                foreach (IConstructTriplePattern p in pattern.TriplePatterns.OfType<IConstructTriplePattern>())
                {
                    subj = p.Subject.Construct(constructContext);
                    pred = p.Predicate.Construct(constructContext);
                    obj = p.Object.Construct(constructContext);

                    target.Assert(new Triple(subj, pred, obj));
                }
            }
        }
 /// <summary>
 /// Constructs a Node based on the given Set
 /// </summary>
 /// <param name="context">Construct Context</param>
 protected internal override INode Construct(ConstructContext context)
 {
     return context.GetNode(this._node);
 }
Exemple #4
0
        /// <summary>
        /// Evaluates the Command in the given Context
        /// </summary>
        /// <param name="context">Evaluation Context</param>
        public override void Evaluate(SparqlUpdateEvaluationContext context)
        {
            bool defGraphOk = false;
            bool datasetOk = false;

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

                //Set Active Graph for the WHERE based upon the WITH clause
                //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 (!this.UsingUris.Any())
                {
                    if (this._graphUri != null)
                    {
                        context.Data.SetActiveGraph(this._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/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 this.UsingUris)
                {
                    query.AddDefaultGraph(u);
                }
                foreach (Uri u in this.UsingNamedUris)
                {
                    query.AddNamedGraph(u);
                }
                SparqlEvaluationContext queryContext = new SparqlEvaluationContext(query, context.Data, context.QueryProcessor);
                if (this.UsingUris.Any())
                {
                    //If there are USING URIs set the Active Graph to be formed of the Graphs with those URIs
                    context.Data.SetActiveGraph(this._usingUris);
                    datasetOk = true;
                }
                BaseMultiset results = queryContext.Evaluate(where);
                if (this.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 from which we are deleting
                IGraph g = context.Data.GetModifiableGraph(this._graphUri);

                //Delete the Triples for each Solution
                foreach (ISet s in queryContext.OutputMultiset.Sets)
                {
                    List<Triple> deletedTriples = new List<Triple>();

                    //Triples from raw Triple Patterns
                    try
                    {
                        ConstructContext constructContext = new ConstructContext(g, s, true);
                        foreach (IConstructTriplePattern p in this._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 throw an error this means we couldn't construct for this solution so the
                        //solution is ignored this graph
                    }

                    //Triples from GRAPH clauses
                    foreach (GraphPattern gp in this._deletePattern.ChildGraphPatterns)
                    {
                        deletedTriples.Clear();
                        try
                        {
                            String graphUri;
                            switch (gp.GraphSpecifier.TokenType)
                            {
                                case Token.URI:
                                    graphUri = gp.GraphSpecifier.Value;
                                    break;
                                case Token.VARIABLE:
                                    if (s.ContainsVariable(gp.GraphSpecifier.Value))
                                    {
                                        INode temp = s[gp.GraphSpecifier.Value.Substring(1)];
                                        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 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();
            }
        }
Exemple #5
0
 /// <summary>
 /// Constructs a Triple from a Set based on this Triple Pattern
 /// </summary>
 /// <param name="context">Construct Context</param>
 /// <returns></returns>
 public Triple Construct(ConstructContext context)
 {
     return new Triple(Tools.CopyNode(this._subj.Construct(context), context.Graph), Tools.CopyNode(this._pred.Construct(context), context.Graph), Tools.CopyNode(this._obj.Construct(context), context.Graph));
 }
Exemple #6
0
        /// <summary>
        /// Constructs a Node based on the given Set
        /// </summary>
        /// <param name="context">Construct Context</param>
        /// <returns>The Node which is bound to this Variable in this Solution</returns>
        protected internal override INode Construct(ConstructContext context)
        {
            INode value = context.Set[this._varname];

            if (value == null) throw new RdfQueryException("Unable to construct a Value for this Variable for this solution as it is bound to a null");
            switch (value.NodeType)
            {
                case NodeType.Blank:
                    if (!context.PreserveBlankNodes && value.GraphUri != null)
                    {
                        //Rename Blank Node based on the Graph Uri Hash Code
                        int hash = value.GraphUri.GetEnhancedHashCode();
                        if (hash >= 0)
                        {
                            return new BlankNode(context.Graph, ((IBlankNode)value).InternalID + "-" + value.GraphUri.GetEnhancedHashCode());
                        }
                        else
                        {
                            return new BlankNode(context.Graph, ((IBlankNode)value).InternalID + hash);
                        }
                    }
                    else
                    {
                        return new BlankNode(context.Graph, ((IBlankNode)value).InternalID);
                    }

                default:
                    return context.GetNode(value);
            }
        }
        /// <summary>
        /// Processes a DELETE DATA command
        /// </summary>
        /// <param name="cmd">DELETE Data Command</param>
        public void ProcessDeleteDataCommand(DeleteDataCommand cmd)
        {
            if (this._manager is IUpdateableGenericIOManager)
            {
                ((IUpdateableGenericIOManager)this._manager).Update(cmd.ToString());
            }
            else
            {
                //Check IO Behaviour
                //For a delete we either need the ability to Update Delete Triples or to Overwrite Graphs
                //Firstly check behaviour persuant to default graph if applicable
                if (cmd.DataPattern.TriplePatterns.OfType<IConstructTriplePattern>().Any())
                {
                    //Must support notion of default graph
                    if ((this._manager.IOBehaviour & IOBehaviour.HasDefaultGraph) == 0) throw new SparqlUpdateException("The underlying store does not support the notion of an explicit unnamed Default Graph required to process this command");
                    //Must allow either OverwriteDefault or CanUpdateDeleteTriples
                    if ((this._manager.IOBehaviour & IOBehaviour.CanUpdateDeleteTriples) == 0 && (this._manager.IOBehaviour & IOBehaviour.OverwriteDefault) == 0) throw new SparqlUpdateException("The underlying store does not support the required IO Behaviour to implement this command");
                }
                //Then check behaviour persuant to named graphs if applicable
                if (cmd.DataPattern.HasChildGraphPatterns)
                {
                    //Must support named graphs
                    if ((this._manager.IOBehaviour & IOBehaviour.HasNamedGraphs) == 0) throw new SparqlUpdateException("The underlying store does not support the notion of named graphs required to process this command");
                    //Must allow either CanUpdateDeleteTriples or OverwriteNamed
                    if ((this._manager.IOBehaviour & IOBehaviour.CanUpdateDeleteTriples) == 0 && (this._manager.IOBehaviour & IOBehaviour.OverwriteNamed) == 0) throw new SparqlUpdateException("The underlying store does not support the required IO Behaviour to implement this command");
                }

                //Split the Pattern into the set of Graph Patterns
                List<GraphPattern> patterns = new List<GraphPattern>();
                if (cmd.DataPattern.IsGraph)
                {
                    patterns.Add(cmd.DataPattern);
                }
                else if (cmd.DataPattern.TriplePatterns.Count > 0 || cmd.DataPattern.HasChildGraphPatterns)
                {
                    if (cmd.DataPattern.TriplePatterns.Count > 0)
                    {
                        patterns.Add(new GraphPattern());
                        cmd.DataPattern.TriplePatterns.ForEach(tp => patterns[0].AddTriplePattern(tp));
                    }
                    cmd.DataPattern.ChildGraphPatterns.ForEach(gp => patterns.Add(gp));
                }
                else
                {
                    //If no Triple Patterns and No Child Graph Patterns nothing to do
                    return;
                }

                foreach (GraphPattern pattern in patterns)
                {
                    if (!this.IsValidDataPattern(pattern, false)) throw new SparqlUpdateException("Cannot evaluate a DELETE DATA command where any of the Triple Patterns are not concrete triples - variables are not permitted");

                    Uri graphUri = null;
                    if (pattern.IsGraph)
                    {
                        switch (pattern.GraphSpecifier.TokenType)
                        {
                            case Token.QNAME:
                                throw new NotSupportedException("Graph Specifiers as QNames for DELETE DATA Commands are not supported - please specify an absolute URI instead");
                            case Token.URI:
                                graphUri = UriFactory.Create(pattern.GraphSpecifier.Value);
                                break;
                            default:
                                throw new SparqlUpdateException("Cannot evaluate an DELETE DATA Command as the Graph Specifier is not a QName/URI");
                        }
                    }

                    Graph g = new Graph();
                    if (!this._manager.UpdateSupported)
                    {
                        //If the Graph to be deleted from is empty then can skip as will have no affect on the Graph
                        this._manager.LoadGraph(g, graphUri);
                        if (g.IsEmpty) continue;
                    }
                    //Note that if the Manager supports Triple Level updates we won't load the Graph
                    //so we can't know whether it is empty or not and so can't skip the delete step

                    //Delete the actual Triples
                    INode subj, pred, obj;
                    ConstructContext context = new ConstructContext(g, null, true);
                    foreach (IConstructTriplePattern p in pattern.TriplePatterns.OfType<IConstructTriplePattern>())
                    {
                        subj = p.Subject.Construct(context);
                        pred = p.Predicate.Construct(context);
                        obj = p.Object.Construct(context);

                        if (!this._manager.UpdateSupported)
                        {
                            //If we don't support update then we'll have loaded the existing graph
                            //so we'll use this to remove the relevant triples to get to the intended state of
                            //the graph
                            g.Retract(new Triple(subj, pred, obj));
                        }
                        else
                        {
                            //If we do support update then we'll have an empty graph which we'll use to store
                            //up the set of triples to be removed
                            g.Assert(new Triple(subj, pred, obj));
                        }
                    }

                    if (this._manager.UpdateSupported)
                    {
                        this._manager.UpdateGraph(graphUri, Enumerable.Empty<Triple>(), g.Triples);
                    }
                    else
                    {
                        this._manager.SaveGraph(g);
                    }
                }
            }
        }
        /// <summary>
        /// Processes an INSERT command
        /// </summary>
        /// <param name="cmd">Insert Command</param>
        /// <remarks>
        /// <para>
        /// <strong>Note:</strong> The underlying manager must implement the <see cref="IQueryableGenericIOManager">IQueryableGenericIOManager</see> interface in order for INSERT commands to be processed
        /// </para>
        /// </remarks>
        public void ProcessInsertCommand(InsertCommand cmd)
        {
            if (this._manager is IUpdateableGenericIOManager)
            {
                ((IUpdateableGenericIOManager)this._manager).Update(cmd.ToString());
            }
            else
            {
                if (this._manager is IQueryableGenericIOManager)
                {
                    //Check IO Behaviour
                    //For a insert we either need the ability to Update Add Triples or to Overwrite Graphs
                    //Firstly check behaviour persuant to default graph if applicable
                    if (cmd.InsertPattern.TriplePatterns.OfType<IConstructTriplePattern>().Any())
                    {
                        //Must support notion of default graph
                        if ((this._manager.IOBehaviour & IOBehaviour.HasDefaultGraph) == 0) throw new SparqlUpdateException("The underlying store does not support the notion of an explicit unnamed Default Graph required to process this command");
                        //Must allow either OverwriteDefault or CanUpdateAddTriples
                        if ((this._manager.IOBehaviour & IOBehaviour.CanUpdateAddTriples) == 0 && (this._manager.IOBehaviour & IOBehaviour.OverwriteDefault) == 0) throw new SparqlUpdateException("The underlying store does not support the required IO Behaviour to implement this command");
                    }
                    //Then check behaviour persuant to named graphs if applicable
                    if (cmd.InsertPattern.HasChildGraphPatterns)
                    {
                        //Must support named graphs
                        if ((this._manager.IOBehaviour & IOBehaviour.HasNamedGraphs) == 0) throw new SparqlUpdateException("The underlying store does not support the notion of named graphs required to process this command");
                        //Must allow either CanUpdateAddTriples or OverwriteNamed
                        if ((this._manager.IOBehaviour & IOBehaviour.CanUpdateAddTriples) == 0 && (this._manager.IOBehaviour & IOBehaviour.OverwriteNamed) == 0) throw new SparqlUpdateException("The underlying store does not support the required IO Behaviour to implement this command");
                    }

                    //First build and make the query to get a Result Set
                    String queryText = "SELECT * WHERE " + cmd.WherePattern.ToString();
                    SparqlQueryParser parser = new SparqlQueryParser();
                    SparqlQuery query = parser.ParseFromString(queryText);
                    if (cmd.GraphUri != null && !cmd.UsingUris.Any()) query.AddDefaultGraph(cmd.GraphUri);
                    foreach (Uri u in cmd.UsingUris)
                    {
                        query.AddDefaultGraph(u);
                    }
                    foreach (Uri u in cmd.UsingNamedUris)
                    {
                        query.AddNamedGraph(u);
                    }

                    Object results = ((IQueryableGenericIOManager)this._manager).Query(query.ToString());
                    if (results is SparqlResultSet)
                    {
                        //Now need to transform the Result Set back to a Multiset
                        Multiset mset = new Multiset((SparqlResultSet)results);

                        //Generate the Triples for each Solution
                        List<Triple> insertedTriples = new List<Triple>();
                        Dictionary<String, List<Triple>> insertedGraphTriples = new Dictionary<string, List<Triple>>();
                        foreach (ISet s in mset.Sets)
                        {
                            List<Triple> tempInsertedTriples = new List<Triple>();
                            try
                            {
                                ConstructContext context = new ConstructContext(null, s, true);
                                foreach (IConstructTriplePattern p in cmd.InsertPattern.TriplePatterns.OfType<IConstructTriplePattern>())
                                {
                                    try
                                    {
                                        tempInsertedTriples.Add(p.Construct(context));
                                    }
                                    catch (RdfQueryException)
                                    {
                                        //If we get an error here then it means we couldn't construct a specific
                                        //triple so we continue anyway
                                    }
                                }
                                insertedTriples.AddRange(tempInsertedTriples);
                            }
                            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
                            }

                            //Triples from GRAPH clauses
                            foreach (GraphPattern gp in cmd.InsertPattern.ChildGraphPatterns)
                            {
                                tempInsertedTriples.Clear();
                                try
                                {
                                    String graphUri;
                                    switch (gp.GraphSpecifier.TokenType)
                                    {
                                        case Token.URI:
                                            graphUri = gp.GraphSpecifier.Value;
                                            break;
                                        case Token.VARIABLE:
                                            if (s.ContainsVariable(gp.GraphSpecifier.Value))
                                            {
                                                INode temp = s[gp.GraphSpecifier.Value.Substring(1)];
                                                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 (!insertedGraphTriples.ContainsKey(graphUri)) insertedGraphTriples.Add(graphUri, new List<Triple>());
                                    ConstructContext context = new ConstructContext(null, s, true);
                                    foreach (IConstructTriplePattern p in gp.TriplePatterns.OfType<IConstructTriplePattern>())
                                    {
                                        try
                                        {
                                            tempInsertedTriples.Add(p.Construct(context));
                                        }
                                        catch (RdfQueryException)
                                        {
                                            //If we get an error here then it means we couldn't construct a specific
                                            //triple so we continue anyway
                                        }
                                    }
                                    insertedGraphTriples[graphUri].AddRange(tempInsertedTriples);
                                }
                                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
                                }
                            }
                        }

                        //Now decide how to apply the update
                        if (this._manager.UpdateSupported)
                        {
                            this._manager.UpdateGraph(cmd.GraphUri, insertedTriples, Enumerable.Empty<Triple>());
                            foreach (KeyValuePair<String, List<Triple>> graphInsertion in insertedGraphTriples)
                            {
                                this._manager.UpdateGraph(graphInsertion.Key, graphInsertion.Value, Enumerable.Empty<Triple>());
                            }
                        }
                        else
                        {
                            Graph g = new Graph();
                            this._manager.LoadGraph(g, cmd.GraphUri);
                            g.Assert(insertedTriples);
                            this._manager.SaveGraph(g);

                            foreach (KeyValuePair<String, List<Triple>> graphInsertion in insertedGraphTriples)
                            {
                                g = new Graph();
                                this._manager.LoadGraph(g, graphInsertion.Key);
                                g.Assert(graphInsertion.Value);
                                this._manager.SaveGraph(g);
                            }
                        }
                    }
                    else
                    {
                        throw new SparqlUpdateException("Cannot evaluate an INSERT Command as the underlying Store failed to answer the query for the WHERE portion of the command as expected");
                    }
                }
                else
                {
                    throw new NotSupportedException("INSERT commands are not supported by this Update Processor as the manager for the underlying Store does not provide Query capabilities which are necessary to process this command");
                }
            }
        }
        /// <summary>
        /// Processes an INSERT DATA command
        /// </summary>
        /// <param name="cmd">Insert Data Command</param>
        public void ProcessInsertDataCommand(InsertDataCommand cmd)
        {
            if (this._manager is IUpdateableGenericIOManager)
            {
                ((IUpdateableGenericIOManager)this._manager).Update(cmd.ToString());
            }
            else
            {
                //Check IO Behaviour
                //For a insert we either need the ability to Update Delete Triples or to Overwrite Graphs
                //Firstly check behaviour persuant to default graph if applicable
                if (cmd.DataPattern.TriplePatterns.OfType<IConstructTriplePattern>().Any())
                {
                    //Must support notion of default graph
                    if ((this._manager.IOBehaviour & IOBehaviour.HasDefaultGraph) == 0) throw new SparqlUpdateException("The underlying store does not support the notion of an explicit unnamed Default Graph required to process this command");
                    //Must allow either OverwriteDefault or CanUpdateAddTriples
                    if ((this._manager.IOBehaviour & IOBehaviour.CanUpdateAddTriples) == 0 && (this._manager.IOBehaviour & IOBehaviour.OverwriteDefault) == 0) throw new SparqlUpdateException("The underlying store does not support the required IO Behaviour to implement this command");
                }
                //Then check behaviour persuant to named graphs if applicable
                if (cmd.DataPattern.HasChildGraphPatterns)
                {
                    //Must support named graphs
                    if ((this._manager.IOBehaviour & IOBehaviour.HasNamedGraphs) == 0) throw new SparqlUpdateException("The underlying store does not support the notion of named graphs required to process this command");
                    //Must allow either CanUpdateAddTriples or OverwriteNamed
                    if ((this._manager.IOBehaviour & IOBehaviour.CanUpdateAddTriples) == 0 && (this._manager.IOBehaviour & IOBehaviour.OverwriteNamed) == 0) throw new SparqlUpdateException("The underlying store does not support the required IO Behaviour to implement this command");
                }

                //Split the Pattern into the set of Graph Patterns
                List<GraphPattern> patterns = new List<GraphPattern>();
                if (cmd.DataPattern.IsGraph)
                {
                    patterns.Add(cmd.DataPattern);
                }
                else if (cmd.DataPattern.TriplePatterns.Count > 0 || cmd.DataPattern.HasChildGraphPatterns)
                {
                    if (cmd.DataPattern.TriplePatterns.Count > 0)
                    {
                        patterns.Add(new GraphPattern());
                        cmd.DataPattern.TriplePatterns.ForEach(tp => patterns[0].AddTriplePattern(tp));
                    }
                    cmd.DataPattern.ChildGraphPatterns.ForEach(gp => patterns.Add(gp));
                }
                else
                {
                    //If no Triple Patterns and No Child Graph Patterns nothing to do
                    return;
                }

                foreach (GraphPattern pattern in patterns)
                {
                    if (!this.IsValidDataPattern(pattern, false)) throw new SparqlUpdateException("Cannot evaluate an INSERT DATA command where any of the Triple Patterns are not concrete triples - variables are not permitted");

                    Uri graphUri = null;
                    if (pattern.IsGraph)
                    {
                        switch (pattern.GraphSpecifier.TokenType)
                        {
                            case Token.QNAME:
                                throw new NotSupportedException("Graph Specifiers as QNames for INSERT DATA Commands are not supported - please specify an absolute URI instead");
                            case Token.URI:
                                graphUri = UriFactory.Create(pattern.GraphSpecifier.Value);
                                break;
                            default:
                                throw new SparqlUpdateException("Cannot evaluate an INSERT DATA Command as the Graph Specifier is not a QName/URI");
                        }
                    }

                    Graph g = new Graph();
                    if (!this._manager.UpdateSupported) this._manager.LoadGraph(g, graphUri);

                    //Insert the actual Triples
                    INode subj, pred, obj;
                    ConstructContext context = new ConstructContext(g, null, true);
                    foreach (IConstructTriplePattern p in pattern.TriplePatterns.OfType<IConstructTriplePattern>())
                    {
                        subj = p.Subject.Construct(context);
                        pred = p.Predicate.Construct(context);
                        obj = p.Object.Construct(context);

                        g.Assert(new Triple(subj, pred, obj));
                    }

                    if (this._manager.UpdateSupported)
                    {
                        this._manager.UpdateGraph(graphUri, g.Triples, Enumerable.Empty<Triple>());
                    }
                    else
                    {
                        this._manager.SaveGraph(g);
                    }
                }
            }
        }
        /// <summary>
        /// Processes an INSERT/DELETE command
        /// </summary>
        /// <param name="cmd">Insert/Delete Command</param>
        public void ProcessModifyCommand(ModifyCommand cmd)
        {
            if (this._manager is IUpdateableGenericIOManager)
            {
                ((IUpdateableGenericIOManager)this._manager).Update(cmd.ToString());
            }
            else
            {
                if (this._manager is IQueryableGenericIOManager)
                {
                    //First build and make the query to get a Result Set
                    String queryText = "SELECT * WHERE " + cmd.WherePattern.ToString();
                    SparqlQueryParser parser = new SparqlQueryParser();
                    SparqlQuery query = parser.ParseFromString(queryText);
                    if (cmd.GraphUri != null && !cmd.UsingUris.Any()) query.AddDefaultGraph(cmd.GraphUri);
                    foreach (Uri u in cmd.UsingUris)
                    {
                        query.AddDefaultGraph(u);
                    }
                    foreach (Uri u in cmd.UsingNamedUris)
                    {
                        query.AddNamedGraph(u);
                    }

                    Object results = ((IQueryableGenericIOManager)this._manager).Query(query.ToString());
                    if (results is SparqlResultSet)
                    {
                        //Now need to transform the Result Set back to a Multiset
                        Multiset mset = new Multiset((SparqlResultSet)results);

                        //Generate the Triples for each Solution
                        List<Triple> deletedTriples = new List<Triple>();
                        Dictionary<String, List<Triple>> deletedGraphTriples = new Dictionary<string, List<Triple>>();
                        foreach (Set s in mset.Sets)
                        {
                            List<Triple> tempDeletedTriples = new List<Triple>();
                            try
                            {
                                ConstructContext context = new ConstructContext(null, s, true);
                                foreach (IConstructTriplePattern p in cmd.DeletePattern.TriplePatterns.OfType<IConstructTriplePattern>())
                                {
                                    try
                                    {
                                        tempDeletedTriples.Add(p.Construct(context));
                                    }
                                    catch (RdfQueryException)
                                    {
                                        //If we get an error here then it means we could not construct a specific
                                        //triple so we continue anyway
                                    }
                                }
                                deletedTriples.AddRange(tempDeletedTriples);
                            }
                            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 cmd.DeletePattern.ChildGraphPatterns)
                            {
                                tempDeletedTriples.Clear();
                                try
                                {
                                    String graphUri;
                                    switch (gp.GraphSpecifier.TokenType)
                                    {
                                        case Token.URI:
                                            graphUri = gp.GraphSpecifier.Value;
                                            break;
                                        case Token.VARIABLE:
                                            if (s.ContainsVariable(gp.GraphSpecifier.Value))
                                            {
                                                INode temp = s[gp.GraphSpecifier.Value.Substring(1)];
                                                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 (!deletedGraphTriples.ContainsKey(graphUri)) deletedGraphTriples.Add(graphUri, new List<Triple>());
                                    ConstructContext context = new ConstructContext(null, s, true);
                                    foreach (IConstructTriplePattern p in gp.TriplePatterns.OfType<IConstructTriplePattern>())
                                    {
                                        try
                                        {
                                            tempDeletedTriples.Add(p.Construct(context));
                                        }
                                        catch (RdfQueryException)
                                        {
                                            //If we throw an error this means we couldn't construct a specific
                                            //triple so we continue anyway
                                        }
                                    }
                                    deletedGraphTriples[graphUri].AddRange(tempDeletedTriples);
                                }
                                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
                                }
                            }
                        }

                        //Generate the Triples for each Solution
                        List<Triple> insertedTriples = new List<Triple>();
                        Dictionary<String, List<Triple>> insertedGraphTriples = new Dictionary<string, List<Triple>>();
                        foreach (Set s in mset.Sets)
                        {
                            List<Triple> tempInsertedTriples = new List<Triple>();
                            try
                            {
                                ConstructContext context = new ConstructContext(null, s, true);
                                foreach (IConstructTriplePattern p in cmd.InsertPattern.TriplePatterns.OfType<IConstructTriplePattern>())
                                {
                                    try
                                    {
                                        tempInsertedTriples.Add(p.Construct(context));
                                    }
                                    catch (RdfQueryException)
                                    {
                                        //If we get an error here then it means we couldn't construct a specific
                                        //triple so we continue anyway
                                    }
                                }
                                insertedTriples.AddRange(tempInsertedTriples);
                            }
                            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 cmd.InsertPattern.ChildGraphPatterns)
                            {
                                tempInsertedTriples.Clear();
                                try
                                {
                                    String graphUri;
                                    switch (gp.GraphSpecifier.TokenType)
                                    {
                                        case Token.URI:
                                            graphUri = gp.GraphSpecifier.Value;
                                            break;
                                        case Token.VARIABLE:
                                            if (s.ContainsVariable(gp.GraphSpecifier.Value))
                                            {
                                                INode temp = s[gp.GraphSpecifier.Value.Substring(1)];
                                                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 (!insertedGraphTriples.ContainsKey(graphUri)) insertedGraphTriples.Add(graphUri, new List<Triple>());
                                    ConstructContext context = new ConstructContext(null, s, true);
                                    foreach (IConstructTriplePattern p in gp.TriplePatterns.OfType<IConstructTriplePattern>())
                                    {
                                        try
                                        {
                                            tempInsertedTriples.Add(p.Construct(context));
                                        }
                                        catch (RdfQueryException)
                                        {
                                            //If we get an error here it means we couldn't construct a specific
                                            //triple so we continue anyway
                                        }
                                    }
                                    insertedGraphTriples[graphUri].AddRange(tempInsertedTriples);
                                }
                                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
                                }
                            }
                        }

                        //Now decide how to apply the update
                        if (this._manager.UpdateSupported)
                        {
                            this._manager.UpdateGraph(cmd.GraphUri, insertedTriples, deletedTriples);
                            //We do these two operations sequentially even if in some cases they could be combined to ensure that the underlying
                            //Manager doesn't do any optimisations which would have the result of our updates not being properly applied
                            //e.g. ignoring Triples which are both asserted and retracted in one update
                            foreach (KeyValuePair<String, List<Triple>> graphDeletion in deletedGraphTriples)
                            {
                                this._manager.UpdateGraph(graphDeletion.Key, Enumerable.Empty<Triple>(), graphDeletion.Value);
                            }
                            foreach (KeyValuePair<String, List<Triple>> graphInsertion in insertedGraphTriples)
                            {
                                this._manager.UpdateGraph(graphInsertion.Key, graphInsertion.Value, Enumerable.Empty<Triple>());
                            }
                        }
                        else
                        {
                            Graph g = new Graph();
                            this._manager.LoadGraph(g, cmd.GraphUri);
                            g.Retract(deletedTriples);
                            this._manager.SaveGraph(g);

                            foreach (String graphUri in deletedGraphTriples.Keys.Concat(insertedGraphTriples.Keys).Distinct())
                            {
                                g = new Graph();
                                this._manager.LoadGraph(g, graphUri);
                                if (deletedGraphTriples.ContainsKey(graphUri)) g.Retract(deletedGraphTriples[graphUri]);
                                if (insertedGraphTriples.ContainsKey(graphUri)) g.Assert(insertedGraphTriples[graphUri]);
                                this._manager.SaveGraph(g);
                            }
                        }
                    }
                    else
                    {
                        throw new SparqlUpdateException("Cannot evaluate an INSERT/DELETE Command as the underlying Store failed to answer the query for the WHERE portion of the command as expected");
                    }
                }
                else
                {
                    throw new NotSupportedException("INSERT/DELETE commands are not supported by this Update Processor as the manager for the underlying Store does not provide Query capabilities which are necessary to process this command");
                }
            }
        }
        /// <summary>
        /// Processes an INSERT DATA command
        /// </summary>
        /// <param name="cmd">Insert Data Command</param>
        public void ProcessInsertDataCommand(InsertDataCommand cmd)
        {
            if (this._manager is IUpdateableGenericIOManager)
            {
                ((IUpdateableGenericIOManager)this._manager).Update(cmd.ToString());
            }
            else
            {
                //Split the Pattern into the set of Graph Patterns
                List<GraphPattern> patterns = new List<GraphPattern>();
                if (cmd.DataPattern.IsGraph)
                {
                    patterns.Add(cmd.DataPattern);
                }
                else if (cmd.DataPattern.TriplePatterns.Count > 0 || cmd.DataPattern.HasChildGraphPatterns)
                {
                    if (cmd.DataPattern.TriplePatterns.Count > 0)
                    {
                        patterns.Add(new GraphPattern());
                        cmd.DataPattern.TriplePatterns.ForEach(tp => patterns[0].AddTriplePattern(tp));
                    }
                    cmd.DataPattern.ChildGraphPatterns.ForEach(gp => patterns.Add(gp));
                }
                else
                {
                    //If no Triple Patterns and No Child Graph Patterns nothing to do
                    return;
                }

                foreach (GraphPattern pattern in patterns)
                {
                    if (!this.IsValidDataPattern(pattern, false)) throw new SparqlUpdateException("Cannot evaluate an INSERT DATA command where any of the Triple Patterns are not concrete triples - variables are not permitted");

                    Uri graphUri = null;
                    if (pattern.IsGraph)
                    {
                        switch (pattern.GraphSpecifier.TokenType)
                        {
                            case Token.QNAME:
                                throw new NotImplementedException("Graph Specifiers as QNames for INSERT DATA Commands are not supported - please specify an absolute URI instead");
                            case Token.URI:
                                graphUri = new Uri(pattern.GraphSpecifier.Value);
                                break;
                            default:
                                throw new SparqlUpdateException("Cannot evaluate an INSERT DATA Command as the Graph Specifier is not a QName/URI");
                        }
                    }

                    Graph g = new Graph();
                    if (!this._manager.UpdateSupported) this._manager.LoadGraph(g, graphUri);

                    //Insert the actual Triples
                    INode subj, pred, obj;
                    ConstructContext context = new ConstructContext(g, null, true);
                    foreach (IConstructTriplePattern p in pattern.TriplePatterns.OfType<IConstructTriplePattern>())
                    {
                        subj = p.Subject.Construct(context);
                        pred = p.Predicate.Construct(context);
                        obj = p.Object.Construct(context);

                        g.Assert(new Triple(subj, pred, obj));
                    }

                    if (this._manager.UpdateSupported)
                    {
                        this._manager.UpdateGraph(graphUri, g.Triples, Enumerable.Empty<Triple>());
                    }
                    else
                    {
                        this._manager.SaveGraph(g);
                    }
                }
            }
        }
 /// <summary>
 /// Returns a Blank Node with a fixed ID scoped to whichever graph is provided
 /// </summary>
 /// <param name="context">Construct Context</param>
 protected internal override INode Construct(ConstructContext context)
 {
     if (context.Graph != null)
     {
         IBlankNode b = context.Graph.GetBlankNode(this._id);
         if (b != null)
         {
             return b;
         }
         else
         {
             return context.Graph.CreateBlankNode(this._id);
         }
     }
     else
     {
         return new BlankNode(context.Graph, this._id);
     }
 }
        /// <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 = this._wherePattern.ToAlgebra();

                //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 (!this.UsingUris.Any())
                {
                    if (this._graphUri != null)
                    {
                        context.Data.SetActiveGraph(this._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 this.UsingNamedUris)
                {
                    query.AddNamedGraph(u);
                }
                SparqlEvaluationContext queryContext = new SparqlEvaluationContext(query, context.Data);
                if (this.UsingUris.Any())
                {
                    //If there are USING URIs set the Active Graph to be formed of the Graphs with those URIs
                    context.Data.SetActiveGraph(this._usingUris);
                    datasetOk = true;
                }
                BaseMultiset results = where.Evaluate(queryContext);
                if (this.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;
                }

                //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
                //HashSet<Uri> insertedGraphs = new HashSet<Uri>();
                IGraph g;
                if (context.Data.HasGraph(this._graphUri))
                {
                    g = context.Data.GetModifiableGraph(this._graphUri);
                }
                else
                {
                    //insertedGraphs.Add(this._graphUri);
                    g = new Graph();
                    g.BaseUri = this._graphUri;
                    context.Data.AddGraph(g);
                    g = context.Data.GetModifiableGraph(this._graphUri);
                }

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

                    //Triples from raw Triple Patterns
                    try
                    {
                        ConstructContext constructContext = new ConstructContext(g, s, true);
                        foreach (IConstructTriplePattern p in this._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);
                    }
                    catch (RdfQueryException)
                    {
                        //If we throw an error 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 this._insertPattern.ChildGraphPatterns)
                    {
                        insertedTriples.Clear();
                        try
                        {
                            String graphUri;
                            switch (gp.GraphSpecifier.TokenType)
                            {
                                case Token.URI:
                                    graphUri = gp.GraphSpecifier.Value;
                                    break;
                                case Token.VARIABLE:
                                    if (s.ContainsVariable(gp.GraphSpecifier.Value))
                                    {
                                        INode temp = s[gp.GraphSpecifier.Value.Substring(1)];
                                        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 = new Uri(graphUri);
                            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);
                            }

                            //Do the actual Insertions
                            ConstructContext constructContext = new ConstructContext(h, s, true);
                            foreach (IConstructTriplePattern p in gp.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
                                }
                            }
                            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
                        }
                    }
                }
            }
            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();
            }
        }