/// <summary> /// Saves a Store in TriG (Turtle with Named Graphs) format. /// </summary> /// <param name="store">Store to save.</param> /// <param name="writer">Writer to save to.</param> /// <param name="leaveOpen">Boolean flag indicating if <paramref name="writer"/> should be left open after the store is saved.</param> public void Save(ITripleStore store, TextWriter writer, bool leaveOpen) { if (store == null) { throw new RdfOutputException("Cannot output a null Triple Store"); } if (writer == null) { throw new RdfOutputException("Cannot output to a null writer"); } TriGWriterContext context = new TriGWriterContext(store, writer, _prettyprint, _allowHiSpeed, _compressionLevel, _n3compat); // Check there's something to do if (context.Store.Graphs.Count == 0) { if (!leaveOpen) { context.Output.Close(); } return; } // Write the Header of the File foreach (var g in context.Store.Graphs) { context.NamespaceMap.Import(g.NamespaceMap); } if (context.CompressionLevel > WriterCompressionLevel.None) { // Only add @prefix declarations if compression is enabled context.QNameMapper = new ThreadSafeQNameOutputMapper(context.NamespaceMap); foreach (string prefix in context.NamespaceMap.Prefixes) { if (TurtleSpecsHelper.IsValidQName(prefix + ":")) { context.Output.WriteLine("@prefix " + prefix + ": <" + context.FormatUri(context.NamespaceMap.GetNamespaceUri(prefix)) + ">."); } } context.Output.WriteLine(); } else { context.QNameMapper = new ThreadSafeQNameOutputMapper(new NamespaceMapper(true)); } if (_useMultiThreading) { // Standard Multi-Threaded Writing // Queue the Graphs to be written foreach (IGraph g in context.Store.Graphs) { context.Add(g.BaseUri); } // Start making the async calls var workers = new Task[_threads]; for (int i = 0; i < _threads; i++) { workers[i] = Task.Factory.StartNew(() => SaveGraphs(context)); } try { Task.WaitAll(workers); } catch (AggregateException ex) { var outputException = new RdfThreadedOutputException(WriterErrorMessages.ThreadedOutputFailure("TriG")); foreach (var innerException in ex.InnerExceptions) { outputException.AddException(innerException); } } finally { // Make sure to close the output if (!leaveOpen) { context.Output.Close(); } } } else { try { // Optional Single Threaded Writing foreach (IGraph g in store.Graphs) { TurtleWriterContext graphContext = new TurtleWriterContext(g, new System.IO.StringWriter(), context.PrettyPrint, context.HighSpeedModePermitted); if (context.CompressionLevel > WriterCompressionLevel.None) { graphContext.NodeFormatter = new TurtleFormatter(context.QNameMapper); } else { graphContext.NodeFormatter = new UncompressedTurtleFormatter(); } context.Output.WriteLine(GenerateGraphOutput(context, graphContext)); } // Make sure to close the output if (!leaveOpen) { context.Output.Close(); } } catch { try { // Close the output if (!leaveOpen) { context.Output.Close(); } } catch { // No catch actions, just cleaning up the output stream } throw; } } }
/// <summary> /// Saves a Store in TriG (Turtle with Named Graphs) format /// </summary> /// <param name="store">Store to save</param> /// <param name="writer">Writer to save to</param> public void Save(ITripleStore store, TextWriter writer) { if (store == null) { throw new RdfOutputException("Cannot output a null Triple Store"); } if (writer == null) { throw new RdfOutputException("Cannot output to a null writer"); } TriGWriterContext context = new TriGWriterContext(store, writer, this._prettyprint, this._allowHiSpeed, this._compressionLevel, this._n3compat); //Check there's something to do if (context.Store.Graphs.Count == 0) { context.Output.Close(); return; } //Write the Header of the File foreach (IGraph g in context.Store.Graphs) { context.NamespaceMap.Import(g.NamespaceMap); } if (context.CompressionLevel > WriterCompressionLevel.None) { //Only add @prefix declarations if compression is enabled context.QNameMapper = new ThreadSafeQNameOutputMapper(context.NamespaceMap); foreach (String prefix in context.NamespaceMap.Prefixes) { if (TurtleSpecsHelper.IsValidQName(prefix + ":")) { context.Output.WriteLine("@prefix " + prefix + ": <" + context.FormatUri(context.NamespaceMap.GetNamespaceUri(prefix)) + ">."); } } context.Output.WriteLine(); } else { context.QNameMapper = new ThreadSafeQNameOutputMapper(new NamespaceMapper(true)); } if (this._useMultiThreading) { //Standard Multi-Threaded Writing //Queue the Graphs to be written foreach (IGraph g in context.Store.Graphs) { context.Add(g.BaseUri); } //Start making the async calls List <IAsyncResult> results = new List <IAsyncResult>(); SaveGraphsDelegate d = new SaveGraphsDelegate(this.SaveGraphs); for (int i = 0; i < this._threads; i++) { results.Add(d.BeginInvoke(context, null, null)); } //Wait for all the async calls to complete WaitHandle.WaitAll(results.Select(r => r.AsyncWaitHandle).ToArray()); RdfThreadedOutputException outputEx = new RdfThreadedOutputException(WriterErrorMessages.ThreadedOutputFailure("TriG")); foreach (IAsyncResult result in results) { try { d.EndInvoke(result); } catch (Exception ex) { outputEx.AddException(ex); } } //Make sure to close the output context.Output.Close(); //If there were any errors we'll throw an RdfThreadedOutputException now if (outputEx.InnerExceptions.Any()) { throw outputEx; } } else { try { //Optional Single Threaded Writing foreach (IGraph g in store.Graphs) { TurtleWriterContext graphContext = new TurtleWriterContext(g, new System.IO.StringWriter(), context.PrettyPrint, context.HighSpeedModePermitted); if (context.CompressionLevel > WriterCompressionLevel.None) { graphContext.NodeFormatter = new TurtleFormatter(context.QNameMapper); } else { graphContext.NodeFormatter = new UncompressedTurtleFormatter(); } context.Output.WriteLine(this.GenerateGraphOutput(context, graphContext)); } //Make sure to close the output context.Output.Close(); } catch { try { //Close the output context.Output.Close(); } catch { //No catch actions, just cleaning up the output stream } throw; } } }