From 52140d52210eda0f25ecab9f89b5c73473e9d8e0 Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Sun, 17 Apr 2016 18:57:29 +0100 Subject: Add CLI for .NET version --- .gitignore | 3 + dotnet/Mammoth.Cli/Mammoth.Cli.csproj | 44 +++++++++ dotnet/Mammoth.Cli/Program.cs | 11 +++ dotnet/Mammoth.Cli/Properties/AssemblyInfo.cs | 27 +++++ dotnet/Mammoth.sln | 6 ++ dotnet/Mammoth/Couscous/Adapters.cs | 13 +++ dotnet/Mammoth/Couscous/java/io/Closeable.cs | 7 +- dotnet/Mammoth/Couscous/java/io/File.cs | 15 +++ dotnet/Mammoth/Couscous/java/io/InputStream.cs | 2 +- dotnet/Mammoth/Couscous/java/nio/file/Path.cs | 11 ++- .../mammoth/internal/docx/InMemoryDocxFile.cs | 17 ++++ .../mammoth/internal/docx/ZippedDocxFile.cs | 26 +++++ .../mammoth/internal/util/Base64Encoding.cs | 12 ++- .../mammoth/internal/util/PassThroughException.cs | 8 ++ .../Mammoth/Couscous/mammoth/internal/util/Sets.cs | 3 +- .../mammoth/internal/xml/parsing/SimpleSax.cs | 31 +++++- dotnet/Mammoth/DocumentConverter.cs | 57 +++++++++++ dotnet/Mammoth/IResult.cs | 8 ++ dotnet/Mammoth/Mammoth.csproj | 9 ++ dotnet/Mammoth/SimpleResult.cs | 22 +++++ .../org/zwobble/mammoth/DocumentConverter.java | 83 +--------------- .../internal/InternalDocumentConverter.java | 110 +++++++++++++++++++++ .../mammoth/internal/docx/ZippedDocxFile.java | 5 + 23 files changed, 438 insertions(+), 92 deletions(-) create mode 100644 dotnet/Mammoth.Cli/Mammoth.Cli.csproj create mode 100644 dotnet/Mammoth.Cli/Program.cs create mode 100644 dotnet/Mammoth.Cli/Properties/AssemblyInfo.cs create mode 100644 dotnet/Mammoth/Couscous/java/io/File.cs create mode 100644 dotnet/Mammoth/Couscous/mammoth/internal/docx/InMemoryDocxFile.cs create mode 100644 dotnet/Mammoth/Couscous/mammoth/internal/docx/ZippedDocxFile.cs create mode 100644 dotnet/Mammoth/DocumentConverter.cs create mode 100644 dotnet/Mammoth/IResult.cs create mode 100644 dotnet/Mammoth/SimpleResult.cs create mode 100644 src/main/java/org/zwobble/mammoth/internal/InternalDocumentConverter.java diff --git a/.gitignore b/.gitignore index a08e5b4..8822de7 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,6 @@ /dotnet/Mammoth/generated.cs /dotnet/Mammoth/bin /dotnet/Mammoth/obj +/dotnet/Mammoth.Cli/bin +/dotnet/Mammoth.Cli/obj +*.userprefs diff --git a/dotnet/Mammoth.Cli/Mammoth.Cli.csproj b/dotnet/Mammoth.Cli/Mammoth.Cli.csproj new file mode 100644 index 0000000..f7e125e --- /dev/null +++ b/dotnet/Mammoth.Cli/Mammoth.Cli.csproj @@ -0,0 +1,44 @@ + + + + Debug + AnyCPU + {20602E78-EEBD-407B-B8C3-EDB6254BD663} + Exe + Mammoth.Cli + Mammoth.Cli + v4.5 + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + true + + + full + true + bin\Release + prompt + 4 + true + + + + + + + + + + + + {51C5CBD6-8809-4D5E-BABE-1787A16F5ED8} + Mammoth + + + \ No newline at end of file diff --git a/dotnet/Mammoth.Cli/Program.cs b/dotnet/Mammoth.Cli/Program.cs new file mode 100644 index 0000000..f45b100 --- /dev/null +++ b/dotnet/Mammoth.Cli/Program.cs @@ -0,0 +1,11 @@ +using System; +using Mammoth; + +namespace Mammoth.Cli { + internal class Program { + public static void Main(string[] args) { + var result = new DocumentConverter().ConvertToHtml(args[0]); + Console.WriteLine(result.Value); + } + } +} diff --git a/dotnet/Mammoth.Cli/Properties/AssemblyInfo.cs b/dotnet/Mammoth.Cli/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..e68abd2 --- /dev/null +++ b/dotnet/Mammoth.Cli/Properties/AssemblyInfo.cs @@ -0,0 +1,27 @@ +using System.Reflection; +using System.Runtime.CompilerServices; + +// Information about this assembly is defined by the following attributes. +// Change them to the values specific to your project. + +[assembly: AssemblyTitle ("Mammoth.Cli")] +[assembly: AssemblyDescription ("")] +[assembly: AssemblyConfiguration ("")] +[assembly: AssemblyCompany ("")] +[assembly: AssemblyProduct ("")] +[assembly: AssemblyCopyright ("mick")] +[assembly: AssemblyTrademark ("")] +[assembly: AssemblyCulture ("")] + +// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". +// The form "{Major}.{Minor}.*" will automatically update the build and revision, +// and "{Major}.{Minor}.{Build}.*" will update just the revision. + +[assembly: AssemblyVersion ("1.0.*")] + +// The following attributes are used to specify the signing key for the assembly, +// if desired. See the Mono documentation for more information about signing. + +//[assembly: AssemblyDelaySign(false)] +//[assembly: AssemblyKeyFile("")] + diff --git a/dotnet/Mammoth.sln b/dotnet/Mammoth.sln index cd369cf..7dae37b 100644 --- a/dotnet/Mammoth.sln +++ b/dotnet/Mammoth.sln @@ -3,12 +3,18 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2012 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mammoth", "Mammoth\Mammoth.csproj", "{51C5CBD6-8809-4D5E-BABE-1787A16F5ED8}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mammoth.Cli", "Mammoth.Cli\Mammoth.Cli.csproj", "{20602E78-EEBD-407B-B8C3-EDB6254BD663}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {20602E78-EEBD-407B-B8C3-EDB6254BD663}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {20602E78-EEBD-407B-B8C3-EDB6254BD663}.Debug|Any CPU.Build.0 = Debug|Any CPU + {20602E78-EEBD-407B-B8C3-EDB6254BD663}.Release|Any CPU.ActiveCfg = Release|Any CPU + {20602E78-EEBD-407B-B8C3-EDB6254BD663}.Release|Any CPU.Build.0 = Release|Any CPU {51C5CBD6-8809-4D5E-BABE-1787A16F5ED8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {51C5CBD6-8809-4D5E-BABE-1787A16F5ED8}.Debug|Any CPU.Build.0 = Debug|Any CPU {51C5CBD6-8809-4D5E-BABE-1787A16F5ED8}.Release|Any CPU.ActiveCfg = Release|Any CPU diff --git a/dotnet/Mammoth/Couscous/Adapters.cs b/dotnet/Mammoth/Couscous/Adapters.cs index a613473..c45f35b 100644 --- a/dotnet/Mammoth/Couscous/Adapters.cs +++ b/dotnet/Mammoth/Couscous/Adapters.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using Mammoth.Couscous.java.lang; using Mammoth.Couscous.java.util; +using Mammoth.Couscous.java.io; namespace Mammoth.Couscous { internal static class FromJava { @@ -82,5 +83,17 @@ namespace Mammoth.Couscous { internal static java.util.List ListToList(IList list) { return new ArrayList(list); } + + internal static java.io.InputStream StreamToInputStream(System.IO.Stream stream) { + return new StreamToInputStreamAdapter(stream); + } + + private class StreamToInputStreamAdapter : InputStream { + public System.IO.Stream Stream { get; } + + internal StreamToInputStreamAdapter(System.IO.Stream stream) { + Stream = stream; + } + } } } diff --git a/dotnet/Mammoth/Couscous/java/io/Closeable.cs b/dotnet/Mammoth/Couscous/java/io/Closeable.cs index 36b2a80..9dc10c5 100644 --- a/dotnet/Mammoth/Couscous/java/io/Closeable.cs +++ b/dotnet/Mammoth/Couscous/java/io/Closeable.cs @@ -1,9 +1,8 @@ using System; -namespace Mammoth.Couscous.java.io -{ - internal interface Closeable - { +namespace Mammoth.Couscous.java.io { + internal interface Closeable { + void close(); } } diff --git a/dotnet/Mammoth/Couscous/java/io/File.cs b/dotnet/Mammoth/Couscous/java/io/File.cs new file mode 100644 index 0000000..abff40a --- /dev/null +++ b/dotnet/Mammoth/Couscous/java/io/File.cs @@ -0,0 +1,15 @@ +using Mammoth.Couscous.java.nio.file; + +namespace Mammoth.Couscous.java.io { + internal class File { + internal string Path { get; } + + internal File(string path) { + Path = path; + } + + internal Path toPath() { + return new Path(Path); + } + } +} diff --git a/dotnet/Mammoth/Couscous/java/io/InputStream.cs b/dotnet/Mammoth/Couscous/java/io/InputStream.cs index 9609a2b..b474bb8 100644 --- a/dotnet/Mammoth/Couscous/java/io/InputStream.cs +++ b/dotnet/Mammoth/Couscous/java/io/InputStream.cs @@ -1,5 +1,5 @@ namespace Mammoth.Couscous.java.io { internal interface InputStream { - + System.IO.Stream Stream { get; } } } diff --git a/dotnet/Mammoth/Couscous/java/nio/file/Path.cs b/dotnet/Mammoth/Couscous/java/nio/file/Path.cs index 6c85cc8..032b4bb 100644 --- a/dotnet/Mammoth/Couscous/java/nio/file/Path.cs +++ b/dotnet/Mammoth/Couscous/java/nio/file/Path.cs @@ -1,9 +1,12 @@ using System; -namespace Mammoth.Couscous.java.nio.file -{ - internal class Path - { +namespace Mammoth.Couscous.java.nio.file { + internal class Path { + private readonly string _path; + + internal Path(string path) { + _path = path; + } } } diff --git a/dotnet/Mammoth/Couscous/mammoth/internal/docx/InMemoryDocxFile.cs b/dotnet/Mammoth/Couscous/mammoth/internal/docx/InMemoryDocxFile.cs new file mode 100644 index 0000000..a475acd --- /dev/null +++ b/dotnet/Mammoth/Couscous/mammoth/internal/docx/InMemoryDocxFile.cs @@ -0,0 +1,17 @@ +using Mammoth.Couscous.java.io; +using Mammoth.Couscous.java.util; + +namespace Mammoth.Couscous.org.zwobble.mammoth.@internal.docx { + internal class InMemoryDocxFile : DocxFile { + internal static DocxFile fromStream(InputStream stream) { + return new InMemoryDocxFile(); + } + + public Optional tryGetInputStream(string name) { + throw new System.NotImplementedException(); + } + + public void close() { + } + } +} diff --git a/dotnet/Mammoth/Couscous/mammoth/internal/docx/ZippedDocxFile.cs b/dotnet/Mammoth/Couscous/mammoth/internal/docx/ZippedDocxFile.cs new file mode 100644 index 0000000..cad7a2f --- /dev/null +++ b/dotnet/Mammoth/Couscous/mammoth/internal/docx/ZippedDocxFile.cs @@ -0,0 +1,26 @@ +using System.IO.Compression; +using Mammoth.Couscous.java.io; +using Mammoth.Couscous.java.util; + +namespace Mammoth.Couscous.org.zwobble.mammoth.@internal.docx { + internal class ZippedDocxFile : DocxFile { + private readonly ZipArchive _zipFile; + + internal ZippedDocxFile(File file) { + _zipFile = ZipFile.OpenRead(file.Path); + } + + public Optional tryGetInputStream(string name) { + var entry = _zipFile.GetEntry(name); + if (entry == null) { + return Optional.empty(); + } else { + return Optional.of(ToJava.StreamToInputStream(entry.Open())); + } + } + + public void close() { + _zipFile.Dispose(); + } + } +} diff --git a/dotnet/Mammoth/Couscous/mammoth/internal/util/Base64Encoding.cs b/dotnet/Mammoth/Couscous/mammoth/internal/util/Base64Encoding.cs index f8270b0..24d2f9c 100644 --- a/dotnet/Mammoth/Couscous/mammoth/internal/util/Base64Encoding.cs +++ b/dotnet/Mammoth/Couscous/mammoth/internal/util/Base64Encoding.cs @@ -3,8 +3,16 @@ using Mammoth.Couscous.java.io; namespace Mammoth.Couscous.org.zwobble.mammoth.@internal.util { internal static class Base64Encoding { - internal static string streamToBase64(SupplierWithException stream) { - throw new UnsupportedOperationException(); + internal static string streamToBase64(SupplierWithException streamSupplier) { + using (var stream = streamSupplier.get().Stream) { + return streamToBase64(stream); + } + } + + internal static string streamToBase64(System.IO.Stream stream) { + var memoryStream = new System.IO.MemoryStream(); + stream.CopyTo(memoryStream); + return System.Convert.ToBase64String(memoryStream.ToArray()); } } } diff --git a/dotnet/Mammoth/Couscous/mammoth/internal/util/PassThroughException.cs b/dotnet/Mammoth/Couscous/mammoth/internal/util/PassThroughException.cs index 4bd2a2a..88597e3 100644 --- a/dotnet/Mammoth/Couscous/mammoth/internal/util/PassThroughException.cs +++ b/dotnet/Mammoth/Couscous/mammoth/internal/util/PassThroughException.cs @@ -10,6 +10,14 @@ namespace Mammoth.Couscous.org.zwobble.mammoth.@internal.util { throw new PassThroughException(exception); } } + + internal static T unwrap(SupplierWithException supplier) { + try { + return supplier.get(); + } catch (PassThroughException exception) { + throw exception._exception; + } + } private readonly IOException _exception; diff --git a/dotnet/Mammoth/Couscous/mammoth/internal/util/Sets.cs b/dotnet/Mammoth/Couscous/mammoth/internal/util/Sets.cs index 7843537..bfce619 100644 --- a/dotnet/Mammoth/Couscous/mammoth/internal/util/Sets.cs +++ b/dotnet/Mammoth/Couscous/mammoth/internal/util/Sets.cs @@ -5,8 +5,7 @@ using System; namespace Mammoth.Couscous.org.zwobble.mammoth.@internal.util { - internal static class Sets - { + internal static class Sets { internal static Set set(T[] values) { return new HashSet(new System.Collections.Generic.HashSet(values)); } diff --git a/dotnet/Mammoth/Couscous/mammoth/internal/xml/parsing/SimpleSax.cs b/dotnet/Mammoth/Couscous/mammoth/internal/xml/parsing/SimpleSax.cs index 8ebdf28..65f63c3 100644 --- a/dotnet/Mammoth/Couscous/mammoth/internal/xml/parsing/SimpleSax.cs +++ b/dotnet/Mammoth/Couscous/mammoth/internal/xml/parsing/SimpleSax.cs @@ -1,9 +1,38 @@ using Mammoth.Couscous.java.io; +using Mammoth.Couscous.java.util; +using System.Xml; namespace Mammoth.Couscous.org.zwobble.mammoth.@internal.xml.parsing { internal static class SimpleSax { internal static void parseStream(InputStream input, SimpleSaxHandler handler) { - throw new System.NotImplementedException(); + var reader = XmlReader.Create(input.Stream); + while (reader.Read()) { + switch (reader.NodeType) { + case XmlNodeType.Element: + var name = new ElementName(reader.NamespaceURI, reader.LocalName); + var attributes = new HashMap(); + var isEmpty = reader.IsEmptyElement; + for (int attributeIndex = 0; attributeIndex < reader.AttributeCount; attributeIndex++) { + reader.MoveToAttribute(attributeIndex); + attributes.put(new ElementName(reader.NamespaceURI, reader.LocalName), reader.Value); + } + handler.startElement(name, attributes); + if (isEmpty) { + handler.endElement(); + } + break; + case XmlNodeType.CDATA: + case XmlNodeType.Text: + case XmlNodeType.SignificantWhitespace: + handler.characters(reader.Value); + break; + case XmlNodeType.EntityReference: + throw new System.NotImplementedException(); + case XmlNodeType.EndElement: + handler.endElement(); + break; + } + } } internal static void parseString(string value, SimpleSaxHandler handler) { diff --git a/dotnet/Mammoth/DocumentConverter.cs b/dotnet/Mammoth/DocumentConverter.cs new file mode 100644 index 0000000..eb8c939 --- /dev/null +++ b/dotnet/Mammoth/DocumentConverter.cs @@ -0,0 +1,57 @@ +using System.IO; +using Mammoth.Couscous; +using Mammoth.Couscous.org.zwobble.mammoth.@internal; +using Mammoth.Couscous.org.zwobble.mammoth.@internal.conversion; + +namespace Mammoth { + public class DocumentConverter { + private readonly DocumentToHtmlOptions options; + + public DocumentConverter() : this(DocumentToHtmlOptions._DEFAULT) { + } + + private DocumentConverter(DocumentToHtmlOptions options) { + this.options = options; + } + + public DocumentConverter IdPrefix(string idPrefix) { + return new DocumentConverter(options.idPrefix(idPrefix)); + } + + public DocumentConverter PreserveEmptyParagraphs() { + return new DocumentConverter(options.preserveEmptyParagraphs()); + } + + public DocumentConverter AddStyleMap(string styleMap) { + return new DocumentConverter(options.addStyleMap(styleMap)); + } + + public DocumentConverter DisableDefaultStyleMap() { + return new DocumentConverter(options.disableDefaultStyleMap()); + } + + public IResult ConvertToHtml(Stream stream) { + return new InternalDocumentConverter(options) + .convertToHtml(ToJava.StreamToInputStream(stream)) + .ToResult(); + } + + public IResult ConvertToHtml(string path) { + return new InternalDocumentConverter(options) + .convertToHtml(new Couscous.java.io.File(path)) + .ToResult(); + } + + public IResult ExtractRawText(Stream stream) { + return new InternalDocumentConverter(options) + .extractRawText(ToJava.StreamToInputStream(stream)) + .ToResult(); + } + + public IResult ExtractRawText(string path) { + return new InternalDocumentConverter(options) + .extractRawText(new Couscous.java.io.File(path)) + .ToResult(); + } + } +} diff --git a/dotnet/Mammoth/IResult.cs b/dotnet/Mammoth/IResult.cs new file mode 100644 index 0000000..7088f3a --- /dev/null +++ b/dotnet/Mammoth/IResult.cs @@ -0,0 +1,8 @@ +using System.Collections.Generic; + +namespace Mammoth { + public interface IResult { + T Value { get; } + ISet Warnings { get; } + } +} diff --git a/dotnet/Mammoth/Mammoth.csproj b/dotnet/Mammoth/Mammoth.csproj index ac380f8..1fe296d 100644 --- a/dotnet/Mammoth/Mammoth.csproj +++ b/dotnet/Mammoth/Mammoth.csproj @@ -29,14 +29,21 @@ + + + + + + + @@ -61,7 +68,9 @@ + + diff --git a/dotnet/Mammoth/SimpleResult.cs b/dotnet/Mammoth/SimpleResult.cs new file mode 100644 index 0000000..f20cd42 --- /dev/null +++ b/dotnet/Mammoth/SimpleResult.cs @@ -0,0 +1,22 @@ +using System.Collections.Generic; +using Mammoth.Couscous; +using Mammoth.Couscous.org.zwobble.mammoth.@internal.results; + +namespace Mammoth { + internal static class SimpleResult { + internal static IResult ToResult(this InternalResult result) { + var warnings = new HashSet(FromJava.IterableToEnumerable(result.getWarnings())); + return new SimpleResult(result.getValue(), warnings); + } + } + + internal class SimpleResult : IResult { + public T Value { get; } + public ISet Warnings { get; } + + internal SimpleResult(T value, ISet warnings) { + Value = value; + Warnings = warnings; + } + } +} diff --git a/src/main/java/org/zwobble/mammoth/DocumentConverter.java b/src/main/java/org/zwobble/mammoth/DocumentConverter.java index f7112f4..3a21fed 100644 --- a/src/main/java/org/zwobble/mammoth/DocumentConverter.java +++ b/src/main/java/org/zwobble/mammoth/DocumentConverter.java @@ -1,31 +1,11 @@ package org.zwobble.mammoth; -import org.zwobble.mammoth.internal.conversion.DocumentToHtml; +import org.zwobble.mammoth.internal.InternalDocumentConverter; import org.zwobble.mammoth.internal.conversion.DocumentToHtmlOptions; -import org.zwobble.mammoth.internal.documents.DocumentElement; -import org.zwobble.mammoth.internal.documents.HasChildren; -import org.zwobble.mammoth.internal.documents.Paragraph; -import org.zwobble.mammoth.internal.documents.Text; -import org.zwobble.mammoth.internal.docx.DocxFile; -import org.zwobble.mammoth.internal.docx.InMemoryDocxFile; -import org.zwobble.mammoth.internal.docx.ZippedDocxFile; -import org.zwobble.mammoth.internal.html.Html; -import org.zwobble.mammoth.internal.results.InternalResult; -import org.zwobble.mammoth.internal.util.Casts; -import org.zwobble.mammoth.internal.util.PassThroughException; import java.io.File; import java.io.IOException; import java.io.InputStream; -import java.nio.file.Path; -import java.util.List; -import java.util.Optional; -import java.util.function.Function; -import java.util.zip.ZipFile; - -import static org.zwobble.mammoth.internal.docx.DocumentReader.readDocument; -import static org.zwobble.mammoth.internal.util.Iterables.lazyMap; -import static org.zwobble.mammoth.internal.util.Lists.list; public class DocumentConverter { private final DocumentToHtmlOptions options; @@ -77,26 +57,14 @@ public class DocumentConverter { * means that relative paths to other files, such as images, cannot be resolved. */ public Result convertToHtml(InputStream stream) throws IOException { - return PassThroughException.unwrap(() -> - withDocxFile(stream, zipFile -> - convertToHtml(Optional.empty(), zipFile)).toResult()); + return new InternalDocumentConverter(options).convertToHtml(stream).toResult(); } /** * Converts {@code file} into an HTML string. */ public Result convertToHtml(File file) throws IOException { - return PassThroughException.unwrap(() -> - withDocxFile(file, zipFile -> - convertToHtml(Optional.of(file.toPath()), zipFile)).toResult()); - } - - private InternalResult convertToHtml(Optional path, DocxFile zipFile) { - return readDocument(path, zipFile) - .flatMap(nodes -> DocumentToHtml.convertToHtml(nodes, options)) - .map(Html::stripEmpty) - .map(Html::collapse) - .map(Html::write); + return new InternalDocumentConverter(options).convertToHtml(file).toResult(); } /** @@ -105,9 +73,7 @@ public class DocumentConverter { * Each paragraph is followed by two newlines. */ public Result extractRawText(InputStream stream) throws IOException { - return PassThroughException.unwrap(() -> - withDocxFile(stream, zipFile -> - extractRawText(Optional.empty(), zipFile)).toResult()); + return new InternalDocumentConverter(options).extractRawText(stream).toResult(); } /** @@ -116,45 +82,6 @@ public class DocumentConverter { * Each paragraph is followed by two newlines. */ public Result extractRawText(File file) throws IOException { - return PassThroughException.unwrap(() -> - withDocxFile(file, zipFile -> - extractRawText(Optional.of(file.toPath()), zipFile)).toResult()); - } - - private InternalResult extractRawText(Optional path, DocxFile zipFile) { - return readDocument(path, zipFile) - .map(DocumentConverter::extractRawTextOfChildren); - } - - private static T withDocxFile(File file, Function function) throws IOException { - try (DocxFile zipFile = new ZippedDocxFile(new ZipFile(file))) { - return function.apply(zipFile); - } - } - - private static T withDocxFile(InputStream stream, Function function) throws IOException { - try (DocxFile zipFile = InMemoryDocxFile.fromStream(stream)) { - return function.apply(zipFile); - } - } - - private static String extractRawTextOfChildren(HasChildren parent) { - return extractRawText(parent.getChildren()); - } - - private static String extractRawText(List nodes) { - return String.join("", lazyMap(nodes, node -> extractRawText(node))); - } - - private static String extractRawText(DocumentElement node) { - return Casts.tryCast(Text.class, node) - .map(Text::getValue) - .orElseGet(() -> { - List children = Casts.tryCast(HasChildren.class, node) - .map(HasChildren::getChildren) - .orElse(list()); - String suffix = node instanceof Paragraph ? "\n\n" : ""; - return extractRawText(children) + suffix; - }); + return new InternalDocumentConverter(options).extractRawText(file).toResult(); } } diff --git a/src/main/java/org/zwobble/mammoth/internal/InternalDocumentConverter.java b/src/main/java/org/zwobble/mammoth/internal/InternalDocumentConverter.java new file mode 100644 index 0000000..4cc0e28 --- /dev/null +++ b/src/main/java/org/zwobble/mammoth/internal/InternalDocumentConverter.java @@ -0,0 +1,110 @@ +package org.zwobble.mammoth.internal; + +import org.zwobble.mammoth.internal.conversion.DocumentToHtml; +import org.zwobble.mammoth.internal.conversion.DocumentToHtmlOptions; +import org.zwobble.mammoth.internal.documents.DocumentElement; +import org.zwobble.mammoth.internal.documents.HasChildren; +import org.zwobble.mammoth.internal.documents.Paragraph; +import org.zwobble.mammoth.internal.documents.Text; +import org.zwobble.mammoth.internal.docx.DocxFile; +import org.zwobble.mammoth.internal.docx.InMemoryDocxFile; +import org.zwobble.mammoth.internal.docx.ZippedDocxFile; +import org.zwobble.mammoth.internal.html.Html; +import org.zwobble.mammoth.internal.results.InternalResult; +import org.zwobble.mammoth.internal.util.PassThroughException; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Path; +import java.util.List; +import java.util.Optional; +import java.util.function.Function; + +import static org.zwobble.mammoth.internal.docx.DocumentReader.readDocument; +import static org.zwobble.mammoth.internal.util.Casts.tryCast; +import static org.zwobble.mammoth.internal.util.Iterables.lazyMap; +import static org.zwobble.mammoth.internal.util.Lists.list; + +public class InternalDocumentConverter { + private final DocumentToHtmlOptions options; + + public InternalDocumentConverter(DocumentToHtmlOptions options) { + this.options = options; + } + + public InternalResult convertToHtml(InputStream stream) throws IOException { + return PassThroughException.unwrap(() -> + withDocxFile(stream, zipFile -> + convertToHtml(Optional.empty(), zipFile))); + } + + public InternalResult convertToHtml(File file) throws IOException { + return PassThroughException.unwrap(() -> + withDocxFile(file, zipFile -> + convertToHtml(Optional.of(file.toPath()), zipFile))); + } + + private InternalResult convertToHtml(Optional path, DocxFile zipFile) { + return readDocument(path, zipFile) + .flatMap(nodes -> DocumentToHtml.convertToHtml(nodes, options)) + .map(Html::stripEmpty) + .map(Html::collapse) + .map(Html::write); + } + + public InternalResult extractRawText(InputStream stream) throws IOException { + return PassThroughException.unwrap(() -> + withDocxFile(stream, zipFile -> + extractRawText(Optional.empty(), zipFile))); + } + + public InternalResult extractRawText(File file) throws IOException { + return PassThroughException.unwrap(() -> + withDocxFile(file, zipFile -> + extractRawText(Optional.of(file.toPath()), zipFile))); + } + + private InternalResult extractRawText(Optional path, DocxFile zipFile) { + return readDocument(path, zipFile) + .map(InternalDocumentConverter::extractRawTextOfChildren); + } + + private static T withDocxFile(File file, Function function) throws IOException { + DocxFile zipFile = new ZippedDocxFile(file); + try { + return function.apply(zipFile); + } finally { + zipFile.close(); + } + } + + private static T withDocxFile(InputStream stream, Function function) throws IOException { + DocxFile zipFile = InMemoryDocxFile.fromStream(stream); + try { + return function.apply(zipFile); + } finally { + zipFile.close(); + } + } + + private static String extractRawTextOfChildren(HasChildren parent) { + return extractRawText(parent.getChildren()); + } + + private static String extractRawText(List nodes) { + return String.join("", lazyMap(nodes, node -> extractRawText(node))); + } + + private static String extractRawText(DocumentElement node) { + return tryCast(Text.class, node) + .map(Text::getValue) + .orElseGet(() -> { + List children = tryCast(HasChildren.class, node) + .map(HasChildren::getChildren) + .orElse(list()); + String suffix = tryCast(Paragraph.class, node).map(paragraph -> "\n\n").orElse(""); + return extractRawText(children) + suffix; + }); + } +} diff --git a/src/main/java/org/zwobble/mammoth/internal/docx/ZippedDocxFile.java b/src/main/java/org/zwobble/mammoth/internal/docx/ZippedDocxFile.java index d263578..559be1b 100644 --- a/src/main/java/org/zwobble/mammoth/internal/docx/ZippedDocxFile.java +++ b/src/main/java/org/zwobble/mammoth/internal/docx/ZippedDocxFile.java @@ -1,5 +1,6 @@ package org.zwobble.mammoth.internal.docx; +import java.io.File; import java.io.IOException; import java.io.InputStream; import java.util.Optional; @@ -13,6 +14,10 @@ public class ZippedDocxFile implements DocxFile { this.zipFile = zipFile; } + public ZippedDocxFile(File file) throws IOException { + this(new ZipFile(file)); + } + @Override public Optional tryGetInputStream(String name) throws IOException { ZipEntry entry = zipFile.getEntry(name); -- cgit v1.2.3