/// <summary> /// Serialize a <see cref="ReqIF"/> object and write its content in an XML-file in the corresponding path /// </summary> /// <param name="reqIf"> /// The <see cref="ReqIF"/> object to serialize /// </param> /// <param name="fileUri"> /// The path of the output file /// </param> /// <exception cref="ArgumentException"></exception> /// <exception cref="UnauthorizedAccessException"></exception> /// <exception cref="ArgumentNullException"></exception> /// <exception cref="DirectoryNotFoundException"></exception> /// <exception cref="IOException"></exception> /// <exception cref="SecurityException"></exception> public void Serialize(ReqIF reqIf, string fileUri) { if (reqIf == null) { throw new ArgumentNullException("reqIf", "The reqIf object cannot be null."); } if (fileUri == null) { throw new ArgumentNullException("fileUri", "The path of the file cannot be null."); } if (fileUri == string.Empty) { throw new ArgumentOutOfRangeException("fileUri", "The path of the file cannot be empty."); } using (var fs = new FileStream(fileUri, FileMode.Create)) { using (var writer = XmlWriter.Create(fs, new XmlWriterSettings { Indent = true })) { this.xmlSerializer.Serialize(writer, reqIf); } } }
/// <summary> /// Write root xml element and contained objects /// </summary> /// <param name="xmlWriter"> /// The <see cref="XmlWriter"/> used to write the <see cref="ReqIF"/> object /// </param> /// <param name="reqIf"> /// The <see cref="ReqIF"/> object that is to be serialized /// </param> private void WriteXml(XmlWriter xmlWriter, ReqIF reqIf) { xmlWriter.WriteStartDocument(); xmlWriter.WriteStartElement("REQ-IF", DefaultXmlAttributeFactory.ReqIFSchemaUri); reqIf.WriteXml(xmlWriter); xmlWriter.WriteEndElement(); xmlWriter.WriteEndDocument(); }
/// <summary> /// Merge multiple <see cref="ReqIF"/> instances into one <see cref="ReqIF"/> /// </summary> /// <param name="reqifs">The <see cref="ReqIF"/> to merge</param> /// <returns>The <see cref="ReqIF"/></returns> internal static ReqIF MergeReqIf(IReadOnlyList <ReqIF> reqifs) { var reqif = new ReqIF(); reqif.TheHeader.AddRange(reqifs.SelectMany(x => x.TheHeader)); reqif.CoreContent.AddRange(reqifs.SelectMany(x => x.CoreContent)); reqif.ToolExtensions.AddRange(reqifs.SelectMany(x => x.ToolExtensions)); reqif.Lang = reqifs.FirstOrDefault(x => !string.IsNullOrWhiteSpace(x.Lang))?.Lang ?? string.Empty; return(reqif); }
/// <summary> /// write the contents of the <see cref="ReqIF"/> to a file /// </summary> /// <param name="reqIf"> /// The <see cref="ReqIF"/> object to serialize /// </param> /// <param name="stream"> /// The <see cref="Stream"/> to serialize to /// </param> /// <param name="token"> /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. /// </param> /// <returns> /// an awaitable task /// </returns> private async Task WriteXmlToStreamAsync(ReqIF reqIf, Stream stream, CancellationToken token) { if (token.IsCancellationRequested) { token.ThrowIfCancellationRequested(); } using (var writer = XmlWriter.Create(stream, this.CreateXmlWriterSettings(true))) { await this.WriteXmlAsync(writer, reqIf, token); } }
/// <summary> /// Async Serialize a <see cref="ReqIF"/> object and write its content to the provided <see cref="Stream"/> /// </summary> /// <param name="reqIf"> /// The <see cref="ReqIF"/> object to serialize /// </param> /// <param name="stream"> /// The <see cref="Stream"/> to serialize to /// </param> /// <param name="token"> /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. /// </param> /// <exception cref="XmlSchemaValidationException"></exception> /// <exception cref="ArgumentException"></exception> /// <exception cref="UnauthorizedAccessException"></exception> /// <exception cref="ArgumentNullException"></exception> /// <exception cref="DirectoryNotFoundException"></exception> /// <exception cref="IOException"></exception> /// <exception cref="SecurityException"></exception> public Task SerializeAsync(ReqIF reqIf, Stream stream, CancellationToken token) { if (reqIf == null) { throw new ArgumentNullException(nameof(reqIf), "The reqIf object cannot be null."); } if (stream == null) { throw new ArgumentNullException(nameof(stream), "The stream cannot be null."); } return(this.WriteXmlToStreamAsync(reqIf, stream, token)); }
/// <summary> /// Serialize a <see cref="ReqIF"/> object and write its content in an XML-file in the corresponding path /// </summary> /// <param name="reqIf"> /// The <see cref="ReqIF"/> object to serialize /// </param> /// <param name="fileUri"> /// The path of the output file /// </param> /// <param name="validationEventHandler"> /// The <see cref="ValidationEventHandler"/> that processes the result of the reqif validation. /// May be null if validation is off. /// </param> /// <exception cref="XmlSchemaValidationException"></exception> /// <exception cref="ArgumentException"></exception> /// <exception cref="UnauthorizedAccessException"></exception> /// <exception cref="ArgumentNullException"></exception> /// <exception cref="DirectoryNotFoundException"></exception> /// <exception cref="IOException"></exception> /// <exception cref="SecurityException"></exception> public void Serialize(ReqIF reqIf, string fileUri, ValidationEventHandler validationEventHandler) { if (reqIf == null) { throw new ArgumentNullException("reqIf", "The reqIf object cannot be null."); } if (fileUri == null) { throw new ArgumentNullException("fileUri", "The path of the file cannot be null."); } if (fileUri == string.Empty) { throw new ArgumentOutOfRangeException("fileUri", "The path of the file cannot be empty."); } if (this.shouldBeValidated) { using (var writer = new StringWriter()) { this.xmlSerializer.Serialize(writer, reqIf); var xmlDocument = new XmlDocument(); xmlDocument.LoadXml(writer.ToString()); xmlDocument.Schemas = this.reqIFSchemaSet; // throws XmlSchemaValidationException upon failure xmlDocument.Validate(validationEventHandler); using (var xmlTextWriter = new XmlTextWriter(fileUri, Encoding.UTF8) { Formatting = Formatting.Indented }) { xmlDocument.Save(xmlTextWriter); } } } else { using (var writer = XmlWriter.Create(fileUri, new XmlWriterSettings { Indent = true })) { this.xmlSerializer.Serialize(writer, reqIf); } } }
/// <summary> /// Creates the XHTML namespace attribute in case the <see cref="ReqIF"/> document /// contains XHTML data /// </summary> /// <param name="reqIf"> /// The <see cref="ReqIF"/> document that is to be serialized /// </param> /// <returns> /// An instance of <see cref="XmlAttribute"/> /// </returns> internal static XmlAttribute CreateXHTMLNameSpaceAttribute(ReqIF reqIf) { // only add the xhtml namespace if we have any xhtml data if (reqIf.CoreContent.DataTypes.OfType <DatatypeDefinitionXHTML>().Any()) { var xHtmlAttribute = new XmlAttribute { LocalName = "xhtml", Prefix = "xmlns", Value = XHTMLNameSpaceUri }; return(xHtmlAttribute); } return(null); }
/// <summary> /// Serialize a <see cref="ReqIF"/> object and write its content to the provided <see cref="Stream"/> /// </summary> /// <param name="reqIf"> /// The <see cref="ReqIF"/> object to serialize /// </param> /// <param name="stream"> /// The <see cref="Stream"/> to serialize to /// </param> /// <exception cref="ArgumentNullException"></exception> public void Serialize(ReqIF reqIf, Stream stream) { if (reqIf == null) { throw new ArgumentNullException(nameof(reqIf), "The reqIf object cannot be null."); } if (stream == null) { throw new ArgumentNullException(nameof(stream), "The stream cannot be null."); } using (var writer = XmlWriter.Create(stream, this.CreateXmlWriterSettings())) { this.WriteXml(writer, reqIf); } }
/// <summary> /// Asynchronously write root xml element and contained objects /// </summary> /// <param name="xmlWriter"> /// The <see cref="XmlWriter"/> used to write the <see cref="ReqIF"/> object /// </param> /// <param name="reqIf"> /// The <see cref="ReqIF"/> object that is to be serialized /// </param> /// <param name="token"> /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. /// </param> private async Task WriteXmlAsync(XmlWriter xmlWriter, ReqIF reqIf, CancellationToken token) { if (token.IsCancellationRequested) { token.ThrowIfCancellationRequested(); } await xmlWriter.WriteStartDocumentAsync(); await xmlWriter.WriteStartElementAsync(null, "REQ-IF", DefaultXmlAttributeFactory.ReqIFSchemaUri); await reqIf.WriteXmlAsync(xmlWriter, token); await xmlWriter.WriteEndElementAsync(); await xmlWriter.WriteEndDocumentAsync(); }
/// <summary> /// Async Serialize a <see cref="ReqIF"/> object and write its content in an XML-file in the corresponding path /// </summary> /// <param name="reqIf"> /// The <see cref="ReqIF"/> object to serialize /// </param> /// <param name="fileUri"> /// The path of the output file /// </param> /// <param name="token"> /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. /// </param> /// <exception cref="XmlSchemaValidationException"></exception> /// <exception cref="ArgumentException"></exception> /// <exception cref="UnauthorizedAccessException"></exception> /// <exception cref="ArgumentNullException"></exception> /// <exception cref="DirectoryNotFoundException"></exception> /// <exception cref="IOException"></exception> /// <exception cref="SecurityException"></exception> public Task SerializeAsync(ReqIF reqIf, string fileUri, CancellationToken token) { if (reqIf == null) { throw new ArgumentNullException(nameof(reqIf), "The reqIf object cannot be null."); } if (fileUri == null) { throw new ArgumentNullException(nameof(fileUri), "The path of the file cannot be null."); } if (fileUri == string.Empty) { throw new ArgumentOutOfRangeException(nameof(fileUri), "The path of the file cannot be empty."); } return(this.WriteXmlToFileAsync(reqIf, fileUri, token)); }
/// <summary> /// Deserializes a <see cref="ReqIF"/> XML document without validation of the content of the document. /// </summary> /// <param name="xmlFilePath"> /// The Path of the <see cref="ReqIF"/> file to deserialize /// </param> /// <returns> /// A fully dereferenced <see cref="ReqIF"/> object graph /// </returns> private ReqIF NonValidatingDeserialization(string xmlFilePath) { XmlReader xmlReader; var settings = new XmlReaderSettings(); var xmlSerializer = new XmlSerializer(typeof(ReqIF)); try { using (var reader = new FileStream(xmlFilePath, FileMode.Open)) using (var archive = new ZipArchive(reader, ZipArchiveMode.Read)) { var reqIfEntries = archive.Entries.Where(x => x.Name.EndsWith(".reqif", StringComparison.CurrentCultureIgnoreCase)).ToArray(); if (reqIfEntries.Length == 0) { throw new FileNotFoundException($"No reqif file could be found in the archive."); } var reqifs = new List <ReqIF>(); foreach (var zipArchiveEntry in reqIfEntries) { using (xmlReader = XmlReader.Create(zipArchiveEntry.Open())) { reqifs.Add((ReqIF)xmlSerializer.Deserialize(xmlReader)); } } return(ReqIF.MergeReqIf(reqifs)); } } catch (Exception e) { if (e is InvalidDataException || e is NotSupportedException) { using (xmlReader = XmlReader.Create(xmlFilePath, settings)) { return((ReqIF)xmlSerializer.Deserialize(xmlReader)); } } throw; } }
/// <summary> /// Serialize a <see cref="ReqIF"/> object and write its content in an XML-file in the corresponding path /// </summary> /// <param name="reqIf"> /// The <see cref="ReqIF"/> object to serialize /// </param> /// <param name="fileUri"> /// The path of the output file /// </param> /// <exception cref="ArgumentNullException"></exception> /// <exception cref="ArgumentOutOfRangeException"></exception> public void Serialize(ReqIF reqIf, string fileUri) { if (reqIf == null) { throw new ArgumentNullException(nameof(reqIf), "The reqIf object cannot be null."); } if (fileUri == null) { throw new ArgumentNullException(nameof(fileUri), "The path of the file cannot be null."); } if (fileUri == string.Empty) { throw new ArgumentOutOfRangeException(nameof(fileUri), "The path of the file cannot be empty."); } using (var writer = XmlWriter.Create(fileUri, this.CreateXmlWriterSettings())) { this.WriteXml(writer, reqIf); } }
/// <summary> /// Asynchronously deserialize the provided <see cref="Stream"/> to ReqIF /// </summary> /// <param name="stream"> /// The <see cref="Stream"/> that contains the reqifz file to deserialize /// </param> /// <param name="token"> /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. /// </param> /// <param name="validate"> /// a value indicating whether the XML document needs to be validated or not /// </param> /// <param name="validationEventHandler"> /// The <see cref="ValidationEventHandler"/> that processes the result of the <see cref="ReqIF"/> validation. /// </param> /// <returns> /// Fully de-referenced <see cref="IEnumerable{ReqIF}"/> object graphs /// </returns> private async Task <IEnumerable <ReqIF> > DeserializeReqIFAsync(Stream stream, CancellationToken token, bool validate = false, ValidationEventHandler validationEventHandler = null) { XmlReader xmlReader; var settings = this.CreateXmlReaderSettings(validate, validationEventHandler, true); try { using (var archive = new ZipArchive(stream, ZipArchiveMode.Read)) { this.logger.LogTrace("reading from reqifz archive"); var sw = Stopwatch.StartNew(); var reqIfEntries = archive.Entries.Where(x => x.Name.EndsWith(".reqif", StringComparison.CurrentCultureIgnoreCase)).ToArray(); if (reqIfEntries.Length == 0) { throw new FileNotFoundException($"No reqif file could be found in the archive."); } this.logger.LogTrace("found {entries} in the reqif zip archive in {time} [ms]", reqIfEntries.Length, sw.ElapsedMilliseconds); sw.Stop(); if (token.IsCancellationRequested) { token.ThrowIfCancellationRequested(); } var reqifs = new List <ReqIF>(); foreach (var zipArchiveEntry in reqIfEntries) { sw.Start(); this.logger.LogTrace("starting to read xml"); using (xmlReader = XmlReader.Create(zipArchiveEntry.Open(), settings)) { while (await xmlReader.ReadAsync()) { if ((xmlReader.NodeType == XmlNodeType.Element) && (xmlReader.Name == "REQ-IF")) { var reqif = new ReqIF(loggerFactory); await reqif.ReadXmlAsync(xmlReader, token); reqifs.Add(reqif); } } } this.logger.LogTrace("xml read in {time}", sw.ElapsedMilliseconds); sw.Stop(); if (token.IsCancellationRequested) { token.ThrowIfCancellationRequested(); } } return(reqifs); } } catch (Exception e) { if (e is InvalidDataException || e is NotSupportedException) { var sw = Stopwatch.StartNew(); this.logger.LogTrace("reading from reqif file"); using (xmlReader = XmlReader.Create(stream, settings)) { var reqifs = new List <ReqIF>(); while (await xmlReader.ReadAsync()) { if ((xmlReader.NodeType == XmlNodeType.Element) && (xmlReader.Name == "REQ-IF")) { var reqif = new ReqIF(loggerFactory); await reqif.ReadXmlAsync(xmlReader, token); reqifs.Add(reqif); } } this.logger.LogTrace("xml read in {time}", sw.ElapsedMilliseconds); sw.Stop(); return(reqifs); } } throw; } }