From c9d7f701e717331dfd060d487fcca546e838b558 Mon Sep 17 00:00:00 2001 From: Hugo de Paix de Coeur Date: Tue, 23 Feb 2016 13:55:37 +0100 Subject: [PATCH] Use Reader in importMarkup instead of a String --- .../builder/AbstractMarkupDocBuilder.java | 38 ++++++++++------- .../markup/builder/MarkupDocBuilder.java | 15 ++++--- .../builder/asciidoc/AsciiDocBuilder.java | 4 +- .../builder/markdown/MarkdownBuilder.java | 4 +- .../builder/AbstractMarkupDocBuilderTest.java | 41 +++++++++++-------- 5 files changed, 64 insertions(+), 38 deletions(-) diff --git a/src/main/java/io/github/robwin/markup/builder/AbstractMarkupDocBuilder.java b/src/main/java/io/github/robwin/markup/builder/AbstractMarkupDocBuilder.java index 9da2e8dd..985d58d1 100644 --- a/src/main/java/io/github/robwin/markup/builder/AbstractMarkupDocBuilder.java +++ b/src/main/java/io/github/robwin/markup/builder/AbstractMarkupDocBuilder.java @@ -23,8 +23,10 @@ import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; +import java.io.Reader; import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Paths; @@ -268,31 +270,39 @@ public abstract class AbstractMarkupDocBuilder implements MarkupDocBuilder { } @Override - public MarkupDocBuilder importMarkup(String text) { - return importMarkup(text, 0); + public MarkupDocBuilder importMarkup(Reader markupText) throws IOException { + return importMarkup(markupText, 0); } - protected void importMarkup(Markup titlePrefix, String text, int levelOffset) { + protected void importMarkup(Markup titlePrefix, Reader markupText, int levelOffset) throws IOException { if (levelOffset > MAX_TITLE_LEVEL) throw new IllegalArgumentException(String.format("Specified levelOffset (%d) > max levelOffset (%d)", levelOffset, MAX_TITLE_LEVEL)); if (levelOffset < -MAX_TITLE_LEVEL) throw new IllegalArgumentException(String.format("Specified levelOffset (%d) < min levelOffset (%d)", levelOffset, -MAX_TITLE_LEVEL)); + final Pattern titlePattern = Pattern.compile(String.format("^(%s{1,%d})\\s+(.*)$", titlePrefix, MAX_TITLE_LEVEL + 1)); + StringBuffer leveledText = new StringBuffer(); - Matcher sections = Pattern.compile(String.format("^(%s{1,%d})\\s+(.*)$", titlePrefix, MAX_TITLE_LEVEL + 1), Pattern.MULTILINE).matcher(text); + try (BufferedReader bufferedReader = new BufferedReader(markupText)) { + String readLine; + while ((readLine = bufferedReader.readLine()) != null) { + Matcher titleMatcher = titlePattern.matcher(readLine); - while (sections.find()) { - int titleLevel = sections.group(1).length() - 1; - String title = sections.group(2); + while (titleMatcher.find()) { + int titleLevel = titleMatcher.group(1).length() - 1; + String title = titleMatcher.group(2); - if (titleLevel + levelOffset > MAX_TITLE_LEVEL) - throw new IllegalArgumentException(String.format("Specified levelOffset (%d) set title '%s' level (%d) > max title level (%d)", levelOffset, title, titleLevel, MAX_TITLE_LEVEL)); - if (titleLevel + levelOffset < 0) - throw new IllegalArgumentException(String.format("Specified levelOffset (%d) set title '%s' level (%d) < 0", levelOffset, title, titleLevel)); - else - sections.appendReplacement(leveledText, StringUtils.repeat(titlePrefix.toString(), 1 + titleLevel + levelOffset) + " " + title); + if (titleLevel + levelOffset > MAX_TITLE_LEVEL) + throw new IllegalArgumentException(String.format("Specified levelOffset (%d) set title '%s' level (%d) > max title level (%d)", levelOffset, title, titleLevel, MAX_TITLE_LEVEL)); + if (titleLevel + levelOffset < 0) + throw new IllegalArgumentException(String.format("Specified levelOffset (%d) set title '%s' level (%d) < 0", levelOffset, title, titleLevel)); + else + titleMatcher.appendReplacement(leveledText, StringUtils.repeat(titlePrefix.toString(), 1 + titleLevel + levelOffset) + " " + title); + } + titleMatcher.appendTail(leveledText); + leveledText.append(newLine); + } } - sections.appendTail(leveledText); documentBuilder.append(newLine); documentBuilder.append(leveledText.toString()); diff --git a/src/main/java/io/github/robwin/markup/builder/MarkupDocBuilder.java b/src/main/java/io/github/robwin/markup/builder/MarkupDocBuilder.java index 460b67b0..90fa6e80 100644 --- a/src/main/java/io/github/robwin/markup/builder/MarkupDocBuilder.java +++ b/src/main/java/io/github/robwin/markup/builder/MarkupDocBuilder.java @@ -19,6 +19,7 @@ package io.github.robwin.markup.builder; import java.io.IOException; +import java.io.Reader; import java.nio.charset.Charset; import java.util.List; @@ -388,22 +389,26 @@ public interface MarkupDocBuilder { /** * Import some markup text into this builder.
- * This is an alias for {@link #importMarkup(String, int) importMarkup(text, 0)}. + * This is an alias for {@link #importMarkup(Reader, int) importMarkup(markupText, 0)}. + * Newlines are normalized in the process. * - * @param text markup text to import + * @param markupText markup reader to read data from * @return this builder + * @throws IOException if I/O error occurs while reading {@code markupText} */ - MarkupDocBuilder importMarkup(String text); + MarkupDocBuilder importMarkup(Reader markupText) throws IOException; /** * Import some markup text into this builder. + * Newlines are normalized in the process. * - * @param markupText markup text to import + * @param markupText markup reader to read data from * @param levelOffset adapt section leveling by adding {@code levelOffset} [0-5] * @return this builder * @throws IllegalArgumentException if levelOffset is too high for the imported markup + * @throws IOException if I/O error occurs while reading {@code markupText} */ - MarkupDocBuilder importMarkup(String markupText, int levelOffset); + MarkupDocBuilder importMarkup(Reader markupText, int levelOffset) throws IOException; /** * Returns a string representation of the document. diff --git a/src/main/java/io/github/robwin/markup/builder/asciidoc/AsciiDocBuilder.java b/src/main/java/io/github/robwin/markup/builder/asciidoc/AsciiDocBuilder.java index 15ba3cf7..418dee57 100644 --- a/src/main/java/io/github/robwin/markup/builder/asciidoc/AsciiDocBuilder.java +++ b/src/main/java/io/github/robwin/markup/builder/asciidoc/AsciiDocBuilder.java @@ -27,6 +27,8 @@ import io.github.robwin.markup.builder.MarkupTableColumn; import org.apache.commons.collections.CollectionUtils; import java.io.File; +import java.io.IOException; +import java.io.Reader; import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -255,7 +257,7 @@ public class AsciiDocBuilder extends AbstractMarkupDocBuilder { } @Override - public MarkupDocBuilder importMarkup(String markupText, int levelOffset) { + public MarkupDocBuilder importMarkup(Reader markupText, int levelOffset) throws IOException { importMarkup(AsciiDoc.TITLE, markupText, levelOffset); return this; } diff --git a/src/main/java/io/github/robwin/markup/builder/markdown/MarkdownBuilder.java b/src/main/java/io/github/robwin/markup/builder/markdown/MarkdownBuilder.java index 2e0166db..3b195233 100644 --- a/src/main/java/io/github/robwin/markup/builder/markdown/MarkdownBuilder.java +++ b/src/main/java/io/github/robwin/markup/builder/markdown/MarkdownBuilder.java @@ -26,6 +26,8 @@ import io.github.robwin.markup.builder.MarkupTableColumn; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.Validate; +import java.io.IOException; +import java.io.Reader; import java.util.Arrays; import java.util.Collection; import java.util.List; @@ -248,7 +250,7 @@ public class MarkdownBuilder extends AbstractMarkupDocBuilder } @Override - public MarkupDocBuilder importMarkup(String markupText, int levelOffset) { + public MarkupDocBuilder importMarkup(Reader markupText, int levelOffset) throws IOException { importMarkup(Markdown.TITLE, markupText, levelOffset); return this; } diff --git a/src/test/java/io/github/robwin/markup/builder/AbstractMarkupDocBuilderTest.java b/src/test/java/io/github/robwin/markup/builder/AbstractMarkupDocBuilderTest.java index f7985f7f..acd583e0 100644 --- a/src/test/java/io/github/robwin/markup/builder/AbstractMarkupDocBuilderTest.java +++ b/src/test/java/io/github/robwin/markup/builder/AbstractMarkupDocBuilderTest.java @@ -7,6 +7,9 @@ import org.junit.Before; import org.junit.Test; import org.mockito.Mockito; +import java.io.IOException; +import java.io.StringReader; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; import static org.mockito.Mockito.mock; @@ -68,16 +71,16 @@ public class AbstractMarkupDocBuilderTest { assertNormalization(Markdown.SPACE_ESCAPE, "sub-action-html-query-value", " /sub/action.html/?query=value "); } - private void assertImportMarkup(Markup markup, String expected, String text, int levelOffset) { + private void assertImportMarkup(Markup markup, String expected, String text, int levelOffset) throws IOException { builder.documentBuilder = new StringBuilder(); - builder.importMarkup(markup, text, levelOffset); + builder.importMarkup(markup, new StringReader(text), levelOffset); assertEquals(expected, builder.documentBuilder.toString()); } - private void assertImportMarkupException(Markup markup, String expected, String text, int levelOffset) { + private void assertImportMarkupException(Markup markup, String expected, String text, int levelOffset) throws IOException { builder.documentBuilder = new StringBuilder(); try { - builder.importMarkup(markup, text, levelOffset); + builder.importMarkup(markup, new StringReader(text), levelOffset); fail("IllegalArgumentException expected"); } catch (IllegalArgumentException e) { assertEquals(expected, e.getMessage()); @@ -85,19 +88,21 @@ public class AbstractMarkupDocBuilderTest { } @Test - public void testImportMarkupAsciiDoc() { + public void testImportMarkupAsciiDoc() throws IOException { assertImportMarkup(AsciiDoc.TITLE, "\n\n", "", 0); assertImportMarkup(AsciiDoc.TITLE, "\n\n", "", 4); assertImportMarkupException(AsciiDoc.TITLE, "Specified levelOffset (5) > max levelOffset (4)", "", 5); assertImportMarkup(AsciiDoc.TITLE, "\n\n", "", -4); assertImportMarkupException(AsciiDoc.TITLE, "Specified levelOffset (-5) < min levelOffset (-4)", "", -5); - assertImportMarkup(AsciiDoc.TITLE, "\nline 1\nline 2\n", "line 1\nline 2", 0); - assertImportMarkup(AsciiDoc.TITLE, "\nline 1\nline 2\n", "line 1\nline 2", 4); + assertImportMarkup(AsciiDoc.TITLE, "\n= title\nline 1\nline 2\n\n", "= title\r\nline 1\r\nline 2", 0); - assertImportMarkup(AsciiDoc.TITLE, "\n= title\nline 1\nline 2\n", "= title\nline 1\nline 2", 0); - assertImportMarkup(AsciiDoc.TITLE, "\n===== title\nline 1\nline 2\n", "= title\nline 1\nline 2", 4); - assertImportMarkup(AsciiDoc.TITLE, "\n= title\nline 1\nline 2\n", "===== title\nline 1\nline 2", -4); + assertImportMarkup(AsciiDoc.TITLE, "\nline 1\nline 2\n\n", "line 1\nline 2", 0); + assertImportMarkup(AsciiDoc.TITLE, "\nline 1\nline 2\n\n", "line 1\nline 2", 4); + + assertImportMarkup(AsciiDoc.TITLE, "\n= title\nline 1\nline 2\n= title 2\nline 3\n\n", "= title\nline 1\nline 2\n= title 2\nline 3", 0); + assertImportMarkup(AsciiDoc.TITLE, "\n===== title\nline 1\nline 2\n\n", "= title\nline 1\nline 2", 4); + assertImportMarkup(AsciiDoc.TITLE, "\n= title\nline 1\nline 2\n\n", "===== title\nline 1\nline 2", -4); assertImportMarkupException(AsciiDoc.TITLE, "Specified levelOffset (4) set title 'title' level (1) > max title level (4)", "== title\nline 1\nline 2", 4); assertImportMarkupException(AsciiDoc.TITLE, "Specified levelOffset (-1) set title 'title' level (0) < 0", "= title\nline 1\nline 2", -1); @@ -105,19 +110,21 @@ public class AbstractMarkupDocBuilderTest { } @Test - public void testImportMarkupMarkdown() { + public void testImportMarkupMarkdown() throws IOException { assertImportMarkup(Markdown.TITLE, "\n\n", "", 0); assertImportMarkup(Markdown.TITLE, "\n\n", "", 4); - assertImportMarkupException(Markdown.TITLE, "Specified levelOffset (5) > max levelOffset (4)", "", 5); assertImportMarkup(Markdown.TITLE, "\n\n", "", -4); + assertImportMarkupException(Markdown.TITLE, "Specified levelOffset (5) > max levelOffset (4)", "", 5); assertImportMarkupException(Markdown.TITLE, "Specified levelOffset (-5) < min levelOffset (-4)", "", -5); - assertImportMarkup(Markdown.TITLE, "\nline 1\nline 2\n", "line 1\nline 2", 0); - assertImportMarkup(Markdown.TITLE, "\nline 1\nline 2\n", "line 1\nline 2", 4); + assertImportMarkup(Markdown.TITLE, "\n# title\nline 1\nline 2\n\n", "# title\r\nline 1\r\nline 2", 0); - assertImportMarkup(Markdown.TITLE, "\n# title\nline 1\nline 2\n", "# title\nline 1\nline 2", 0); - assertImportMarkup(Markdown.TITLE, "\n##### title\nline 1\nline 2\n", "# title\nline 1\nline 2", 4); - assertImportMarkup(Markdown.TITLE, "\n# title\nline 1\nline 2\n", "##### title\nline 1\nline 2", -4); + assertImportMarkup(Markdown.TITLE, "\nline 1\nline 2\n\n", "line 1\nline 2", 0); + assertImportMarkup(Markdown.TITLE, "\nline 1\nline 2\n\n", "line 1\nline 2", 4); + + assertImportMarkup(Markdown.TITLE, "\n# title\nline 1\nline 2\n# title 2\nline 3\n\n", "# title\nline 1\nline 2\n# title 2\nline 3", 0); + assertImportMarkup(Markdown.TITLE, "\n##### title\nline 1\nline 2\n\n", "# title\nline 1\nline 2", 4); + assertImportMarkup(Markdown.TITLE, "\n# title\nline 1\nline 2\n\n", "##### title\nline 1\nline 2", -4); assertImportMarkupException(Markdown.TITLE, "Specified levelOffset (4) set title 'title' level (1) > max title level (4)", "## title\nline 1\nline 2", 4); assertImportMarkupException(Markdown.TITLE, "Specified levelOffset (-1) set title 'title' level (0) < 0", "# title\nline 1\nline 2", -1);