/// <summary> /// Returns the Graph which is the Merge of the Minimal Spanning Graphs for all the Values resulting from the Query /// </summary> /// <param name="context"></param> /// <returns></returns> public override IGraph Describe(SparqlEvaluationContext context) { //Get a new empty Graph and import the Base Uri and Namespace Map of the Query Graph g = new Graph(); g.BaseUri = context.Query.BaseUri; g.NamespaceMap.Import(context.Query.NamespaceMap); //Build a list of INodes to describe List<INode> nodes = new List<INode>(); foreach (IToken t in context.Query.DescribeVariables) { switch (t.TokenType) { case Token.QNAME: case Token.URI: //Resolve Uri/QName nodes.Add(new UriNode(g, new Uri(Tools.ResolveUriOrQName(t, g.NamespaceMap, g.BaseUri)))); break; case Token.VARIABLE: //Get Variable Values String var = t.Value.Substring(1); if (context.OutputMultiset.ContainsVariable(var)) { foreach (Set s in context.OutputMultiset.Sets) { INode temp = s[var]; if (temp != null) nodes.Add(temp); } } break; default: throw new RdfQueryException("Unexpected Token '" + t.GetType().ToString() + "' in DESCRIBE Variables list"); } } //Rewrite Blank Node IDs for DESCRIBE Results Dictionary<String, INode> bnodeMapping = new Dictionary<string, INode>(); //Get Triples for this Subject Queue<INode> bnodes = new Queue<INode>(); HashSet<INode> expandedBNodes = new HashSet<INode>(); foreach (INode n in nodes) { foreach (Triple t in context.Data.GetTriplesWithSubject(n)) { if (t.Object.NodeType == NodeType.Blank) { if (!expandedBNodes.Contains(t.Object)) bnodes.Enqueue(t.Object); } g.Assert(this.RewriteDescribeBNodes(t, bnodeMapping, g)); } if (n.NodeType == NodeType.Blank) { foreach (Triple t in context.Data.GetTriplesWithPredicate(n)) { if (t.Subject.NodeType == NodeType.Blank) { if (!expandedBNodes.Contains(t.Subject)) bnodes.Enqueue(t.Subject); } if (t.Object.NodeType == NodeType.Blank) { if (!expandedBNodes.Contains(t.Object)) bnodes.Enqueue(t.Object); } g.Assert(this.RewriteDescribeBNodes(t, bnodeMapping, g)); } } foreach (Triple t in context.Data.GetTriplesWithObject(n)) { if (t.Subject.NodeType == NodeType.Blank) { if (!expandedBNodes.Contains(t.Object)) bnodes.Enqueue(t.Subject); } g.Assert(this.RewriteDescribeBNodes(t, bnodeMapping, g)); } } //Expand BNodes while (bnodes.Count > 0) { INode n = bnodes.Dequeue(); if (expandedBNodes.Contains(n)) continue; expandedBNodes.Add(n); foreach (Triple t in context.Data.GetTriplesWithSubject(n)) { if (t.Object.NodeType == NodeType.Blank) { if (!expandedBNodes.Contains(t.Object)) bnodes.Enqueue(t.Object); } g.Assert(this.RewriteDescribeBNodes(t, bnodeMapping, g)); } if (n.NodeType == NodeType.Blank) { foreach (Triple t in context.Data.GetTriplesWithPredicate(n)) { if (t.Subject.NodeType == NodeType.Blank) { if (!expandedBNodes.Contains(t.Subject)) bnodes.Enqueue(t.Subject); } if (t.Object.NodeType == NodeType.Blank) { if (!expandedBNodes.Contains(t.Object)) bnodes.Enqueue(t.Object); } g.Assert(this.RewriteDescribeBNodes(t, bnodeMapping, g)); } } foreach (Triple t in context.Data.GetTriplesWithObject(n)) { if (t.Subject.NodeType == NodeType.Blank) { if (!expandedBNodes.Contains(t.Object)) bnodes.Enqueue(t.Subject); } g.Assert(this.RewriteDescribeBNodes(t, bnodeMapping, g)); } } //Return the Graph g.BaseUri = null; return 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 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 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); } } } }