diff --git a/OfficeFlow.Word.OpenXml.Tests/OfficeFlow.Word.OpenXml.Tests.csproj b/OfficeFlow.Word.OpenXml.Tests/OfficeFlow.Word.OpenXml.Tests.csproj index bd6d9b2..fd94e0a 100644 --- a/OfficeFlow.Word.OpenXml.Tests/OfficeFlow.Word.OpenXml.Tests.csproj +++ b/OfficeFlow.Word.OpenXml.Tests/OfficeFlow.Word.OpenXml.Tests.csproj @@ -7,6 +7,7 @@ + @@ -19,4 +20,12 @@ + + + + + + + + diff --git a/OfficeFlow.Word.OpenXml.Tests/Resources/Embedded/EmbeddedResourceDecompressorTests.cs b/OfficeFlow.Word.OpenXml.Tests/Resources/Embedded/EmbeddedResourceDecompressorTests.cs new file mode 100644 index 0000000..9c1eb1e --- /dev/null +++ b/OfficeFlow.Word.OpenXml.Tests/Resources/Embedded/EmbeddedResourceDecompressorTests.cs @@ -0,0 +1,44 @@ +using System.Xml.Linq; +using FluentAssertions; +using OfficeFlow.Word.OpenXml.Resources.Embedded; +using OfficeFlow.Word.OpenXml.Resources.Exceptions; +using Xunit; + +namespace OfficeFlow.Word.OpenXml.Tests.Resources.Embedded +{ + public sealed class EmbeddedResourceDecompressorTests + { + [Fact] + public void Should_decompress_exists_embedded_resource_from_calling_assembly() + { + // Arrange + var expectedXml = new XElement + ( + "document", + new XElement + ( + "body", + new XText("Content") + ) + ); + + var sut = new EmbeddedResourceDecompressor(); + + // Act + var actualXml = sut.Decompress("TestEmbeddedResource.xml.gz"); + + // Assert + actualXml + .Root + .Should() + .BeEquivalentTo(expectedXml); + } + + [Fact] + public void Should_throws_exception_if_resource_not_found_in_calling_assembly() + => new EmbeddedResourceDecompressor() + .Invoking(decompressor => decompressor.Decompress("NotExistsResource.xml.gz")) + .Should() + .Throw(); + } +} \ No newline at end of file diff --git a/OfficeFlow.Word.OpenXml.Tests/Resources/Embedded/TestEmbeddedResource.xml.gz b/OfficeFlow.Word.OpenXml.Tests/Resources/Embedded/TestEmbeddedResource.xml.gz new file mode 100644 index 0000000..06f2728 Binary files /dev/null and b/OfficeFlow.Word.OpenXml.Tests/Resources/Embedded/TestEmbeddedResource.xml.gz differ diff --git a/OfficeFlow.Word.OpenXml/OfficeFlow.Word.OpenXml.csproj b/OfficeFlow.Word.OpenXml/OfficeFlow.Word.OpenXml.csproj index ae3059a..338027e 100644 --- a/OfficeFlow.Word.OpenXml/OfficeFlow.Word.OpenXml.csproj +++ b/OfficeFlow.Word.OpenXml/OfficeFlow.Word.OpenXml.csproj @@ -6,7 +6,16 @@ - + + + + + + + + + + diff --git a/OfficeFlow.Word.OpenXml/Resources/Embedded/Default/bulletNumbering.xml.gz b/OfficeFlow.Word.OpenXml/Resources/Embedded/Default/bulletNumbering.xml.gz new file mode 100644 index 0000000..dc95be8 Binary files /dev/null and b/OfficeFlow.Word.OpenXml/Resources/Embedded/Default/bulletNumbering.xml.gz differ diff --git a/OfficeFlow.Word.OpenXml/Resources/Embedded/Default/decimalNumbering.xml.gz b/OfficeFlow.Word.OpenXml/Resources/Embedded/Default/decimalNumbering.xml.gz new file mode 100644 index 0000000..cf0f419 Binary files /dev/null and b/OfficeFlow.Word.OpenXml/Resources/Embedded/Default/decimalNumbering.xml.gz differ diff --git a/OfficeFlow.Word.OpenXml/Resources/Embedded/Default/numbering.xml.gz b/OfficeFlow.Word.OpenXml/Resources/Embedded/Default/numbering.xml.gz new file mode 100644 index 0000000..84df287 Binary files /dev/null and b/OfficeFlow.Word.OpenXml/Resources/Embedded/Default/numbering.xml.gz differ diff --git a/OfficeFlow.Word.OpenXml/Resources/Embedded/Default/styles.xml.gz b/OfficeFlow.Word.OpenXml/Resources/Embedded/Default/styles.xml.gz new file mode 100644 index 0000000..a53d622 Binary files /dev/null and b/OfficeFlow.Word.OpenXml/Resources/Embedded/Default/styles.xml.gz differ diff --git a/OfficeFlow.Word.OpenXml/Resources/Embedded/Default/wordDocument.xml.gz b/OfficeFlow.Word.OpenXml/Resources/Embedded/Default/wordDocument.xml.gz new file mode 100644 index 0000000..645854b Binary files /dev/null and b/OfficeFlow.Word.OpenXml/Resources/Embedded/Default/wordDocument.xml.gz differ diff --git a/OfficeFlow.Word.OpenXml/Resources/Embedded/Default/wordStyles.xml.gz b/OfficeFlow.Word.OpenXml/Resources/Embedded/Default/wordStyles.xml.gz new file mode 100644 index 0000000..fd0ef36 Binary files /dev/null and b/OfficeFlow.Word.OpenXml/Resources/Embedded/Default/wordStyles.xml.gz differ diff --git a/OfficeFlow.Word.OpenXml/Resources/Embedded/EmbeddedResourceDecompressor.cs b/OfficeFlow.Word.OpenXml/Resources/Embedded/EmbeddedResourceDecompressor.cs new file mode 100644 index 0000000..b08ada6 --- /dev/null +++ b/OfficeFlow.Word.OpenXml/Resources/Embedded/EmbeddedResourceDecompressor.cs @@ -0,0 +1,49 @@ +using System; +using System.IO; +using System.IO.Compression; +using System.Linq; +using System.Reflection; +using System.Xml.Linq; +using OfficeFlow.Word.OpenXml.Resources.Exceptions; +using OfficeFlow.Word.OpenXml.Resources.Interfaces; + +namespace OfficeFlow.Word.OpenXml.Resources.Embedded +{ + public sealed class EmbeddedResourceDecompressor : IResourceDecompressor + { + private readonly Assembly _assembly; + + private static readonly Lazy InstanceFactory = + new Lazy(() => new EmbeddedResourceDecompressor()); + + public static EmbeddedResourceDecompressor Instance + => InstanceFactory.Value; + + public EmbeddedResourceDecompressor() + : this(Assembly.GetCallingAssembly()) + { } + + public EmbeddedResourceDecompressor(Assembly assembly) + => _assembly = assembly; + + private Stream GetResourceStream(string resourceName) + { + var resourcePath = _assembly + .GetManifestResourceNames() + .FirstOrDefault(name => name.EndsWith(resourceName)) + ?? throw new ResourceNotFoundException(resourceName); + + return _assembly.GetManifestResourceStream(resourcePath) + ?? throw new ResourceNotLoadedException(resourceName); + } + + public XDocument Decompress(string resourceName) + { + var stream = GetResourceStream(resourceName); + using var zip = new GZipStream(stream, CompressionMode.Decompress); + using var reader = new StreamReader(zip); + + return XDocument.Load(reader); + } + } +} \ No newline at end of file diff --git a/OfficeFlow.Word.OpenXml/Resources/Exceptions/ResourceNotFoundException.cs b/OfficeFlow.Word.OpenXml/Resources/Exceptions/ResourceNotFoundException.cs new file mode 100644 index 0000000..10ecc54 --- /dev/null +++ b/OfficeFlow.Word.OpenXml/Resources/Exceptions/ResourceNotFoundException.cs @@ -0,0 +1,11 @@ +using System; + +namespace OfficeFlow.Word.OpenXml.Resources.Exceptions +{ + public sealed class ResourceNotFoundException : Exception + { + public ResourceNotFoundException(string resourceName, Exception? innerException = null) + : base($"Resource \"{resourceName}\" not found", innerException) + { } + } +} \ No newline at end of file diff --git a/OfficeFlow.Word.OpenXml/Resources/Exceptions/ResourceNotLoadedException.cs b/OfficeFlow.Word.OpenXml/Resources/Exceptions/ResourceNotLoadedException.cs new file mode 100644 index 0000000..b9e96fd --- /dev/null +++ b/OfficeFlow.Word.OpenXml/Resources/Exceptions/ResourceNotLoadedException.cs @@ -0,0 +1,11 @@ +using System; + +namespace OfficeFlow.Word.OpenXml.Resources.Exceptions +{ + public sealed class ResourceNotLoadedException : Exception + { + public ResourceNotLoadedException(string resourceName, Exception? innerException = null) + : base($"Failed to load resource \"{resourceName}\"", innerException) + { } + } +} \ No newline at end of file diff --git a/OfficeFlow.Word.OpenXml/Resources/Interfaces/IResourceDecompressor.cs b/OfficeFlow.Word.OpenXml/Resources/Interfaces/IResourceDecompressor.cs new file mode 100644 index 0000000..eee70c2 --- /dev/null +++ b/OfficeFlow.Word.OpenXml/Resources/Interfaces/IResourceDecompressor.cs @@ -0,0 +1,9 @@ +using System.Xml.Linq; + +namespace OfficeFlow.Word.OpenXml.Resources.Interfaces +{ + public interface IResourceDecompressor + { + XDocument Decompress(string resourceName); + } +} \ No newline at end of file