- FimFictionAPI: fix NPE
- remote: encryption mode changed because Google
- remote: not compatible with 2.x
-- remote: now use password from config file
+- remote: can now use password from config file
- remote: worse perfs but much better memory usage
- remote: log now includes the time of events
ko='"[ !! ]"';
cols=80;
else
- ok='"`tput bold`[`tput setf 2` OK `tput init``tput bold`]`tput init`"';
- ko='"`tput bold`[`tput setf 4` !! `tput init``tput bold`]`tput init`"';
+ #ok='"`tput bold`[`tput setf 2` OK `tput init``tput bold`]`tput init`"';
+ #ko='"`tput bold`[`tput setf 4` !! `tput init``tput bold`]`tput init`"';
+ ok='"`tput bold`[`tput setaf 2` OK `tput init``tput bold`]`tput init`"';
+ ko='"`tput bold`[`tput setaf 1` !! `tput init``tput bold`]`tput init`"';
cols='"`tput cols`"';
fi;
private Downloader downloader;
private Downloader downloaderNoCache;
private Cache cache;
+ private boolean offline;
/**
* Create a new {@link DataLoader} object.
downloaderNoCache = downloader;
cache = new CacheMemory();
}
+
+ /**
+ * This {@link Downloader} is forbidden to try and connect to the network.
+ * <p>
+ * If TRUE, it will only check the cache (even in no-cache mode!).
+ * <p>
+ * Default is FALSE.
+ *
+ * @return TRUE if offline
+ */
+ public boolean isOffline() {
+ return offline;
+ }
+
+ /**
+ * This {@link Downloader} is forbidden to try and connect to the network.
+ * <p>
+ * If TRUE, it will only check the cache (even in no-cache mode!).
+ * <p>
+ * Default is FALSE.
+ *
+ * @param offline TRUE for offline, FALSE for online
+ */
+ public void setOffline(boolean offline) {
+ this.offline = offline;
+ downloader.setOffline(offline);
+ downloaderNoCache.setOffline(offline);
+
+ // If we don't, we cannot support no-cache using code in OFFLINE mode
+ if (offline) {
+ downloaderNoCache.setCache(cache);
+ } else {
+ downloaderNoCache.setCache(null);
+ }
+ }
/**
* The traces handler for this {@link Cache}.
* @param url
* the resource to open
* @param support
- * the support to use to download the resource
+ * the support to use to download the resource (can be NULL)
* @param stable
* TRUE for more stable resources, FALSE when they often change
*
* is also used for the cache ID if needed (so we can retrieve
* the content with this URL if needed)
* @param support
- * the support to use to download the resource
+ * the support to use to download the resource (can be NULL)
* @param stable
* TRUE for more stable resources, FALSE when they often change
* @param postParams
* @param url
* the resource to open
* @param support
- * the support to use to download the resource
+ * the support to use to download the resource (can be NULL)
* @param stable
* TRUE for more stable resources, FALSE when they often change
*
/**
* The story resume (a.k.a. description).
+ * <p>
+ * This can be NULL if we don't have a resume for this {@link Story}.
*
* @return the resume
*/
String cover = "none";
if (getCover() != null) {
- cover = StringUtils.formatNumber(getCover().getData().length)
+ cover = StringUtils.formatNumber(getCover().getSize())
+ "bytes";
}
private URL source;
private SupportType type;
private URL currentReferer; // with only one 'r', as in 'HTTP'...
+
+ static protected BasicSupportHelper bsHelper = new BasicSupportHelper();
+ static protected BasicSupportImages bsImages = new BasicSupportImages();
+ static protected BasicSupportPara bsPara = new BasicSupportPara(new BasicSupportHelper(), new BasicSupportImages());
/**
* Check if the given resource is supported by this {@link BasicSupport}.
pg.setProgress(50);
if (meta.getCover() == null) {
- meta.setCover(BasicSupportHelper.getDefaultCover(meta.getSubject()));
+ meta.setCover(bsHelper.getDefaultCover(meta.getSubject()));
}
pg.setProgress(60);
String descChapterName = Instance.getTrans().getString(
StringId.DESCRIPTION);
story.getMeta().setResume(
- BasicSupportPara.makeChapter(this, source, 0,
+ bsPara.makeChapter(this, source, 0,
descChapterName, //
getDesc(), isHtml(), null));
}
String content = getChapterContent(chapUrl, i,
pgGetChapterContent);
pgGetChapterContent.done();
- Chapter cc = BasicSupportPara.makeChapter(this, chapUrl, i,
+ Chapter cc = bsPara.makeChapter(this, chapUrl, i,
chapName, content, isHtml(), pgMakeChapter);
pgMakeChapter.done();
*/
public Chapter makeChapter(URL source, int number, String name,
String content) throws IOException {
- return BasicSupportPara.makeChapter(this, source, number, name,
+ return bsPara.makeChapter(this, source, number, name,
content, isHtml(), null);
}
*
* @author niki
*/
-class BasicSupportHelper {
+public class BasicSupportHelper {
/**
* Get the default cover related to this subject (see <tt>.info</tt> files).
*
*
* @return the cover if any, or NULL
*/
- public static Image getDefaultCover(String subject) {
+ public Image getDefaultCover(String subject) {
if (subject != null && !subject.isEmpty()
&& Instance.getCoverDir() != null) {
try {
*
* @return the extensions
*/
- public static String[] getImageExt(boolean emptyAllowed) {
+ public String[] getImageExt(boolean emptyAllowed) {
if (emptyAllowed) {
return new String[] { "", ".png", ".jpg", ".jpeg", ".gif", ".bmp" };
}
* refresh the cache with it if it is.
*
* @param support
- * the linked {@link BasicSupport}
+ * the linked {@link BasicSupport} (can be NULL)
* @param source
- * the story source
+ * the source of the story (for image lookup in the same path if
+ * the source is a file, can be NULL)
* @param line
* the resource to check
*
* @return the image if found, or NULL
*
*/
- public static Image getImage(BasicSupport support, URL source, String line) {
+ public Image getImage(BasicSupport support, URL source, String line) {
URL url = getImageUrl(support, source, line);
if (url != null) {
if ("file".equals(url.getProtocol())) {
* refresh the cache with it if it is.
*
* @param support
- * the linked {@link BasicSupport}
+ * the linked {@link BasicSupport} (can be NULL)
* @param source
- * the story source
+ * the source of the story (for image lookup in the same path if
+ * the source is a file, can be NULL)
* @param line
* the resource to check
*
* @return the image URL if found, or NULL
*
*/
- public static URL getImageUrl(BasicSupport support, URL source, String line) {
+ public URL getImageUrl(BasicSupport support, URL source, String line) {
URL url = null;
if (line != null) {
*
* @return the author without prefixes
*/
- public static String fixAuthor(String author) {
+ public String fixAuthor(String author) {
if (author != null) {
for (String suffix : new String[] { " ", ":" }) {
for (String byString : Instance.getConfig().getList(Config.CONF_BYS)) {
import be.nikiroo.fanfix.Instance;
import be.nikiroo.utils.Image;
+/**
+ * Helper class for {@link BasicSupport}, mostly dedicated to images for
+ * the classes that implement {@link BasicSupport}.
+ *
+ * @author niki
+ */
public class BasicSupportImages {
/**
* Check if the given resource can be a local image or a remote image, then
* @return the image if found, or NULL
*
*/
- static Image getImage(BasicSupport support, File dir, String line) {
+ public Image getImage(BasicSupport support, File dir, String line) {
URL url = getImageUrl(support, dir, line);
if (url != null) {
if ("file".equals(url.getProtocol())) {
* @return the image URL if found, or NULL
*
*/
- static URL getImageUrl(BasicSupport support, File dir, String line) {
+ public URL getImageUrl(BasicSupport support, File dir, String line) {
URL url = null;
if (line != null) {
*
* @return the extensions
*/
- static String[] getImageExt(boolean emptyAllowed) {
+ public String[] getImageExt(boolean emptyAllowed) {
if (emptyAllowed) {
return new String[] { "", ".png", ".jpg", ".jpeg", ".gif", ".bmp" };
}
/**
* Helper class for {@link BasicSupport}, mostly dedicated to {@link Paragraph}
- * and text formating for the {@link BasicSupport} class itself (not its
- * children).
+ * and text formating for the {@link BasicSupport} class.
*
* @author niki
*/
-class BasicSupportPara {
+public class BasicSupportPara {
// quote chars
private static char openQuote = Instance.getTrans().getCharacter(
StringId.OPEN_SINGLE_QUOTE);
private static char closeDoubleQuote = Instance.getTrans().getCharacter(
StringId.CLOSE_DOUBLE_QUOTE);
+ // used by this class:
+ BasicSupportHelper bsHelper;
+ BasicSupportImages bsImages;
+
+ public BasicSupportPara(BasicSupportHelper bsHelper, BasicSupportImages bsImages) {
+ this.bsHelper = bsHelper;
+ this.bsImages = bsImages;
+ }
+
/**
* Create a {@link Chapter} object from the given information, formatting
* the content as it should be.
* @param support
* the linked {@link BasicSupport}
* @param source
- * the source of the story
+ * the source of the story (for image lookup in the same path if
+ * the source is a file, can be NULL)
* @param number
* the chapter number
* @param name
* @throws IOException
* in case of I/O error
*/
- public static Chapter makeChapter(BasicSupport support, URL source,
+ public Chapter makeChapter(BasicSupport support, URL source,
int number, String name, String content, boolean html, Progress pg)
throws IOException {
// Chapter name: process it correctly, then remove the possible
// redundant "Chapter x: " in front of it, or "-" (as in
// "Chapter 5: - Fun!" after the ": " was automatically added)
- String chapterName = BasicSupportPara.processPara(name, false)
+ String chapterName = processPara(name, false)
.getContent().trim();
for (String lang : Instance.getConfig().getList(Config.CONF_CHAPTER)) {
String chapterWord = Instance.getConfig().getStringX(
*
* @return the correctly (or so we hope) quotified paragraphs
*/
- private static List<Paragraph> requotify(Paragraph para, boolean html) {
+ protected List<Paragraph> requotify(Paragraph para, boolean html) {
List<Paragraph> newParas = new ArrayList<Paragraph>();
if (para.getType() == ParagraphType.QUOTE
*
* @return the processed {@link Paragraph}
*/
- private static Paragraph processPara(String line, boolean html) {
+ protected Paragraph processPara(String line, boolean html) {
if (html) {
line = StringUtils.unhtml(line).trim();
}
* Convert the given content into {@link Paragraph}s.
*
* @param support
- * the linked {@link BasicSupport}
+ * the linked {@link BasicSupport} (can be NULL), used to
+ * download optional image content in []
* @param source
- * the source URL of the story
+ * the source URL of the story (for image lookup in the same path
+ * if the source is a file, can be NULL)
* @param content
* the textual content
* @param html
* @throws IOException
* in case of I/O error
*/
- private static List<Paragraph> makeParagraphs(BasicSupport support,
+ protected List<Paragraph> makeParagraphs(BasicSupport support,
URL source, String content, boolean html, Progress pg)
throws IOException {
if (pg == null) {
// Check quotes for "bad" format
List<Paragraph> newParas = new ArrayList<Paragraph>();
for (Paragraph para : paras) {
- newParas.addAll(BasicSupportPara.requotify(para, html));
+ newParas.addAll(requotify(para, html));
}
paras = newParas;
* Convert the given line into a single {@link Paragraph}.
*
* @param support
- * the linked {@link BasicSupport}
+ * the linked {@link BasicSupport} (can be NULL), used to
+ * download optional image content in []
* @param source
- * the source URL of the story
+ * the source URL of the story (for image lookup in the same path
+ * if the source is a file, can be NULL)
* @param line
* the textual content of the paragraph
* @param html
*
* @return the {@link Paragraph}
*/
- private static Paragraph makeParagraph(BasicSupport support, URL source,
+ protected Paragraph makeParagraph(BasicSupport support, URL source,
String line, boolean html) {
Image image = null;
if (line.startsWith("[") && line.endsWith("]")) {
- image = BasicSupportHelper.getImage(support, source, line
+ image = bsHelper.getImage(support, source, line
.substring(1, line.length() - 1).trim());
}
return new Paragraph(image);
}
- return BasicSupportPara.processPara(line, html);
+ return processPara(line, html);
}
/**
* @param paras
* the list of {@link Paragraph}s to fix
*/
- private static void fixBlanksBreaks(List<Paragraph> paras) {
+ protected void fixBlanksBreaks(List<Paragraph> paras) {
boolean space = false;
boolean brk = true;
for (int i = 0; i < paras.size(); i++) {
import java.util.zip.ZipInputStream;
import be.nikiroo.fanfix.Instance;
+import be.nikiroo.fanfix.bundles.Config;
import be.nikiroo.fanfix.data.Chapter;
import be.nikiroo.fanfix.data.MetaData;
import be.nikiroo.fanfix.data.Paragraph;
&& entry.getName().startsWith(getDataPrefix())) {
String entryLName = entry.getName().toLowerCase();
boolean imageEntry = false;
- for (String ext : BasicSupportImages.getImageExt(false)) {
+ for (String ext : bsImages.getImageExt(false)) {
if (entryLName.endsWith(ext)) {
imageEntry = true;
}
}
-
+
if (imageEntry) {
String uuid = meta.getUuid() + "_" + entry.getName();
try {
}
}
}
+
+ String ext = "."
+ + Instance.getConfig()
+ .getString(Config.FILE_FORMAT_IMAGE_FORMAT_COVER)
+ .toLowerCase();
+ String coverName = meta.getUuid() + "_" + basename + ext;
+ Image cover = images.get(coverName);
+ images.remove(coverName);
pg.setProgress(85);
pg.setProgress(90);
- // only the description is kept
+ // only the description/cover is kept
Story origStory = getStoryFromTxt(tmpDir, basename);
if (origStory != null) {
if (origStory.getMeta().getCover() == null) {
}
story.setMeta(origStory.getMeta());
}
+ if (story.getMeta().getCover() == null) {
+ story.getMeta().setCover(cover);
+ }
story.setChapters(new ArrayList<Chapter>());
// Check if we can find non-images chapters, for hybrid-cbz support
package be.nikiroo.fanfix.supported;
import java.io.File;
-import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URISyntaxException;
import be.nikiroo.fanfix.data.MetaData;
import be.nikiroo.utils.IOUtils;
import be.nikiroo.utils.Image;
-import be.nikiroo.utils.streams.MarkableFileInputStream;
import be.nikiroo.utils.StringUtils;
+import be.nikiroo.utils.streams.MarkableFileInputStream;
/**
* Support class for EPUB files created with this program (as we need some
String entryLName = entry.getName().toLowerCase();
boolean imageEntry = false;
- for (String ext : BasicSupportImages.getImageExt(false)) {
+ for (String ext : bsImages.getImageExt(false)) {
if (entryLName.endsWith(ext)) {
imageEntry = true;
}
}
}
- return BasicSupportHelper.fixAuthor(author);
+ return bsHelper.fixAuthor(author);
}
private String getDate(InputStream in) {
package be.nikiroo.fanfix.supported;
import java.io.File;
-import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
// not complete: no "description" tag
public class InfoReader {
+ static protected BasicSupportHelper bsHelper = new BasicSupportHelper();
+ // static protected BasicSupportImages bsImages = new BasicSupportImages();
+ // static protected BasicSupportPara bsPara = new BasicSupportPara(new BasicSupportHelper(), new BasicSupportImages());
+
public static MetaData readMeta(File infoFile, boolean withCover)
throws IOException {
if (infoFile == null) {
if (withCover) {
String infoTag = getInfoTag(in, "COVER");
if (infoTag != null && !infoTag.trim().isEmpty()) {
- meta.setCover(BasicSupportHelper.getImage(null, sourceInfoFile,
+ meta.setCover(bsHelper.getImage(null, sourceInfoFile,
infoTag));
}
if (meta.getCover() == null) {
meta.setFakeCover(Boolean.parseBoolean(getInfoTag(in, "FAKE_COVER")));
if (withCover && meta.getCover() == null) {
- meta.setCover(BasicSupportHelper.getDefaultCover(meta.getSubject()));
+ meta.setCover(bsHelper.getDefaultCover(meta.getSubject()));
}
return meta;
.toLowerCase();
// Without removing ext
- cover = BasicSupportHelper.getImage(null, sourceInfoFile,
+ cover = bsHelper.getImage(null, sourceInfoFile,
basefile.getAbsolutePath() + ext);
// Try without ext
name = name.substring(0, pos);
basefile = new File(basefile.getParent(), name);
- cover = BasicSupportHelper.getImage(null, sourceInfoFile,
+ cover = bsHelper.getImage(null, sourceInfoFile,
basefile.getAbsolutePath() + ext);
}
package be.nikiroo.fanfix.supported;
import java.io.File;
-import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URISyntaxException;
import be.nikiroo.fanfix.Instance;
import be.nikiroo.fanfix.bundles.Config;
+import be.nikiroo.fanfix.data.Chapter;
import be.nikiroo.fanfix.data.MetaData;
+import be.nikiroo.fanfix.data.Paragraph;
import be.nikiroo.utils.Image;
import be.nikiroo.utils.ImageUtils;
-import be.nikiroo.utils.streams.MarkableFileInputStream;
import be.nikiroo.utils.Progress;
+import be.nikiroo.utils.streams.MarkableFileInputStream;
/**
* Support class for local stories encoded in textual format, with a few rules:
author = authorDate.substring(0, pos);
}
- return BasicSupportHelper.fixAuthor(author);
+ return bsHelper.fixAuthor(author);
}
private String getDate() {
@Override
protected String getDesc() throws IOException {
- return getChapterContent(null, 0, null);
+ String content = getChapterContent(null, 0, null).trim();
+ if (!content.isEmpty()) {
+ Chapter desc = bsPara.makeChapter(this, null, 0, "Description",
+ content, isHtml(), null);
+ StringBuilder builder = new StringBuilder();
+ for (Paragraph para : desc) {
+ if (builder.length() > 0) {
+ builder.append("\n");
+ }
+ builder.append(para.getContent());
+ }
+ }
+
+ return content;
}
private Image getCover(File sourceFile) {
}
}
- Image cover = BasicSupportImages.getImage(this,
- sourceFile.getParentFile(), path);
+ Image cover = bsImages.getImage(this, sourceFile.getParentFile(), path);
if (cover != null) {
try {
File tmp = Instance.getTempFiles().createTempFile(
boolean inChap = false;
while (scan.hasNext()) {
String line = scan.next();
- if (detectChapter(line, number) != null) {
+ if (!inChap && detectChapter(line, number) != null) {
inChap = true;
- } else if (inChap && detectChapter(line, number + 1) != null) {
+ } else if (detectChapter(line, number + 1) != null) {
break;
} else if (inChap) {
builder.append(line);
*
* @param line
* the line to check
+ * @param number
+ * the specific chapter number to check for
*
* @return the language or NULL
*/
static private String detectChapter(String line, int number) {
line = line.toUpperCase();
for (String lang : Instance.getConfig().getList(Config.CONF_CHAPTER)) {
- String chapter = Instance.getConfig().getStringX(Config.CONF_CHAPTER,
- lang);
+ String chapter = Instance.getConfig().getStringX(
+ Config.CONF_CHAPTER, lang);
if (chapter != null && !chapter.isEmpty()) {
chapter = chapter.toUpperCase() + " ";
if (line.startsWith(chapter)) {
// We want "[CHAPTER] [number]: [name]", with ": [name]"
// optional
String test = line.substring(chapter.length()).trim();
+
+ String possibleNum = test.trim();
+ if (possibleNum.indexOf(':') > 0) {
+ possibleNum = possibleNum.substring(0,
+ possibleNum.indexOf(':')).trim();
+ }
+
if (test.startsWith(Integer.toString(number))) {
test = test
.substring(Integer.toString(number).length())
import be.nikiroo.utils.test.TestCase;
import be.nikiroo.utils.test.TestLauncher;
-class BasicSupportTest extends TestLauncher {
+class BasicSupportDeprecatedTest extends TestLauncher {
// quote chars
private char openQuote = Instance.getTrans().getCharacter(
StringId.OPEN_SINGLE_QUOTE);
private char closeDoubleQuote = Instance.getTrans().getCharacter(
StringId.CLOSE_DOUBLE_QUOTE);
- public BasicSupportTest(String[] args) {
- super("BasicSupport", args);
+ public BasicSupportDeprecatedTest(String[] args) {
+ super("BasicSupportDeprecated", args);
addSeries(new TestLauncher("General", args) {
{
--- /dev/null
+package be.nikiroo.fanfix.test;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+
+import be.nikiroo.fanfix.Instance;
+import be.nikiroo.fanfix.bundles.StringId;
+import be.nikiroo.fanfix.data.Paragraph;
+import be.nikiroo.fanfix.data.Paragraph.ParagraphType;
+import be.nikiroo.fanfix.data.Story;
+import be.nikiroo.fanfix.supported.BasicSupport;
+import be.nikiroo.fanfix.supported.BasicSupportHelper;
+import be.nikiroo.fanfix.supported.BasicSupportImages;
+import be.nikiroo.fanfix.supported.BasicSupportPara;
+import be.nikiroo.fanfix.supported.SupportType;
+import be.nikiroo.utils.IOUtils;
+import be.nikiroo.utils.Progress;
+import be.nikiroo.utils.test.TestCase;
+import be.nikiroo.utils.test.TestLauncher;
+
+class BasicSupportUtilitiesTest extends TestLauncher {
+ // quote chars
+ private char openQuote = Instance.getTrans().getCharacter(
+ StringId.OPEN_SINGLE_QUOTE);
+ private char closeQuote = Instance.getTrans().getCharacter(
+ StringId.CLOSE_SINGLE_QUOTE);
+ private char openDoubleQuote = Instance.getTrans().getCharacter(
+ StringId.OPEN_DOUBLE_QUOTE);
+ private char closeDoubleQuote = Instance.getTrans().getCharacter(
+ StringId.CLOSE_DOUBLE_QUOTE);
+
+ public BasicSupportUtilitiesTest(String[] args) {
+ super("BasicSupportUtilities", args);
+
+ addSeries(new TestLauncher("General", args) {
+ {
+ addTest(new TestCase("BasicSupport.makeParagraphs()") {
+ @Override
+ public void test() throws Exception {
+ BasicSupportParaPublic bsPara = new BasicSupportParaPublic() {
+ @Override
+ public void fixBlanksBreaks(List<Paragraph> paras) {
+ }
+
+ @Override
+ public List<Paragraph> requotify(Paragraph para, boolean html) {
+ List<Paragraph> paras = new ArrayList<Paragraph>(
+ 1);
+ paras.add(para);
+ return paras;
+ }
+ };
+
+ List<Paragraph> paras = null;
+
+ paras = bsPara.makeParagraphs(null, null, "", true, null);
+ assertEquals(
+ "An empty content should not generate paragraphs",
+ 0, paras.size());
+
+ paras = bsPara.makeParagraphs(null, null,
+ "Line 1</p><p>Line 2</p><p>Line 3</p>", true, null);
+ assertEquals(5, paras.size());
+ assertEquals("Line 1", paras.get(0).getContent());
+ assertEquals(ParagraphType.BLANK, paras.get(1)
+ .getType());
+ assertEquals("Line 2", paras.get(2).getContent());
+ assertEquals(ParagraphType.BLANK, paras.get(3)
+ .getType());
+ assertEquals("Line 3", paras.get(4).getContent());
+
+ paras = bsPara.makeParagraphs(null, null,
+ "<p>Line1</p><p>Line2</p><p>Line3</p>", true, null);
+ assertEquals(6, paras.size());
+ }
+ });
+
+ addTest(new TestCase("BasicSupport.removeDoubleBlanks()") {
+ @Override
+ public void test() throws Exception {
+ BasicSupportParaPublic support = new BasicSupportParaPublic();
+
+ List<Paragraph> paras = null;
+
+ paras = support
+ .makeParagraphs(
+ null,
+ null,
+ "<p>Line1</p><p>Line2</p><p>Line3<br/><br><p></p>",
+ true,
+ null);
+ assertEquals(5, paras.size());
+
+ paras = support
+ .makeParagraphs(
+ null,
+ null,
+ "<p>Line1</p><p>Line2</p><p>Line3<br/><br><p></p>* * *",
+ true,
+ null);
+ assertEquals(5, paras.size());
+
+ paras = support.makeParagraphs(null, null, "1<p>* * *<p>2",
+ true, null);
+ assertEquals(3, paras.size());
+ assertEquals(ParagraphType.BREAK, paras.get(1)
+ .getType());
+
+ paras = support.makeParagraphs(null, null,
+ "1<p><br/><p>* * *<p>2", true, null);
+ assertEquals(3, paras.size());
+ assertEquals(ParagraphType.BREAK, paras.get(1)
+ .getType());
+
+ paras = support.makeParagraphs(null, null,
+ "1<p>* * *<br/><p><br><p>2", true, null);
+ assertEquals(3, paras.size());
+ assertEquals(ParagraphType.BREAK, paras.get(1)
+ .getType());
+
+ paras = support.makeParagraphs(null, null,
+ "1<p><br/><br>* * *<br/><p><br><p>2", true, null);
+ assertEquals(3, paras.size());
+ assertEquals(ParagraphType.BREAK, paras.get(1)
+ .getType());
+ }
+ });
+
+ addTest(new TestCase("BasicSupport.processPara() quotes") {
+ @Override
+ public void test() throws Exception {
+ BasicSupportParaPublic support = new BasicSupportParaPublic();
+
+ Paragraph para;
+
+ // sanity check
+ para = support.processPara("", true);
+ assertEquals(ParagraphType.BLANK, para.getType());
+ //
+
+ para = support.processPara("\"Yes, my Lord!\"", true);
+ assertEquals(ParagraphType.QUOTE, para.getType());
+ assertEquals(openDoubleQuote + "Yes, my Lord!"
+ + closeDoubleQuote, para.getContent());
+
+ para = support.processPara("«Yes, my Lord!»", true);
+ assertEquals(ParagraphType.QUOTE, para.getType());
+ assertEquals(openDoubleQuote + "Yes, my Lord!"
+ + closeDoubleQuote, para.getContent());
+
+ para = support.processPara("'Yes, my Lord!'", true);
+ assertEquals(ParagraphType.QUOTE, para.getType());
+ assertEquals(openQuote + "Yes, my Lord!" + closeQuote,
+ para.getContent());
+
+ para = support.processPara("‹Yes, my Lord!›", true);
+ assertEquals(ParagraphType.QUOTE, para.getType());
+ assertEquals(openQuote + "Yes, my Lord!" + closeQuote,
+ para.getContent());
+ }
+ });
+
+ addTest(new TestCase(
+ "BasicSupport.processPara() double-simple quotes") {
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+
+ super.tearDown();
+ }
+
+ @Override
+ public void test() throws Exception {
+ BasicSupportParaPublic support = new BasicSupportParaPublic();
+
+ Paragraph para;
+
+ para = support.processPara("''Yes, my Lord!''", true);
+ assertEquals(ParagraphType.QUOTE, para.getType());
+ assertEquals(openDoubleQuote + "Yes, my Lord!"
+ + closeDoubleQuote, para.getContent());
+
+ para = support.processPara("‹‹Yes, my Lord!››", true);
+ assertEquals(ParagraphType.QUOTE, para.getType());
+ assertEquals(openDoubleQuote + "Yes, my Lord!"
+ + closeDoubleQuote, para.getContent());
+ }
+ });
+
+ addTest(new TestCase("BasicSupport.processPara() apostrophe") {
+ @Override
+ public void test() throws Exception {
+ BasicSupportParaPublic support = new BasicSupportParaPublic();
+
+ Paragraph para;
+
+ String text = "Nous étions en été, mais cela aurait être l'hiver quand nous n'étions encore qu'à Aubeuge";
+ para = support.processPara(text, true);
+ assertEquals(ParagraphType.NORMAL, para.getType());
+ assertEquals(text, para.getContent());
+ }
+ });
+
+ addTest(new TestCase("BasicSupport.processPara() words count") {
+ @Override
+ public void test() throws Exception {
+ BasicSupportParaPublic support = new BasicSupportParaPublic();
+
+ Paragraph para;
+
+ para = support.processPara("«Yes, my Lord!»", true);
+ assertEquals(3, para.getWords());
+
+ para = support.processPara("One, twee, trois.", true);
+ assertEquals(3, para.getWords());
+ }
+ });
+
+ addTest(new TestCase("BasicSupport.requotify() words count") {
+ @Override
+ public void test() throws Exception {
+ BasicSupportParaPublic support = new BasicSupportParaPublic();
+
+ char openDoubleQuote = Instance.getTrans()
+ .getCharacter(StringId.OPEN_DOUBLE_QUOTE);
+ char closeDoubleQuote = Instance.getTrans()
+ .getCharacter(StringId.CLOSE_DOUBLE_QUOTE);
+
+ String content = null;
+ Paragraph para = null;
+ List<Paragraph> paras = null;
+ long words = 0;
+
+ content = "One, twee, trois.";
+ para = new Paragraph(ParagraphType.NORMAL, content,
+ content.split(" ").length);
+ paras = support.requotify(para, false);
+ words = 0;
+ for (Paragraph p : paras) {
+ words += p.getWords();
+ }
+ assertEquals("Bad words count in a single paragraph",
+ para.getWords(), words);
+
+ content = "Such WoW! So Web2.0! With Colours!";
+ para = new Paragraph(ParagraphType.NORMAL, content,
+ content.split(" ").length);
+ paras = support.requotify(para, false);
+ words = 0;
+ for (Paragraph p : paras) {
+ words += p.getWords();
+ }
+ assertEquals("Bad words count in a single paragraph",
+ para.getWords(), words);
+
+ content = openDoubleQuote + "Such a good idea!"
+ + closeDoubleQuote
+ + ", she said. This ought to be a new para.";
+ para = new Paragraph(ParagraphType.QUOTE, content,
+ content.split(" ").length);
+ paras = support.requotify(para, false);
+ words = 0;
+ for (Paragraph p : paras) {
+ words += p.getWords();
+ }
+ assertEquals(
+ "Bad words count in a requotified paragraph",
+ para.getWords(), words);
+ }
+ });
+ }
+ });
+
+ addSeries(new TestLauncher("Text", args) {
+ {
+ addTest(new TestCase("Chapter detection simple") {
+ private File tmp;
+
+ @Override
+ public void setUp() throws Exception {
+ tmp = File.createTempFile("fanfix-text-file_", ".test");
+ IOUtils.writeSmallFile(tmp.getParentFile(),
+ tmp.getName(), "TITLE"
+ + "\n"//
+ + "By nona"
+ + "\n" //
+ + "\n" //
+ + "Chapter 0: Resumé" + "\n" + "\n"
+ + "'sume." + "\n" + "\n"
+ + "Chapter 1: chap1" + "\n" + "\n"
+ + "Fanfan." + "\n" + "\n"
+ + "Chapter 2: Chap2" + "\n" + "\n" //
+ + "Tulipe." + "\n");
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ tmp.delete();
+ }
+
+ @Override
+ public void test() throws Exception {
+ BasicSupport support = BasicSupport.getSupport(
+ SupportType.TEXT, tmp.toURI().toURL());
+
+ Story story = support.process(null);
+
+ assertEquals(2, story.getChapters().size());
+ assertEquals(1, story.getChapters().get(1)
+ .getParagraphs().size());
+ assertEquals("Tulipe.", story.getChapters().get(1)
+ .getParagraphs().get(0).getContent());
+ }
+ });
+
+ addTest(new TestCase("Chapter detection with String 'Chapter'") {
+ private File tmp;
+
+ @Override
+ public void setUp() throws Exception {
+ tmp = File.createTempFile("fanfix-text-file_", ".test");
+ IOUtils.writeSmallFile(tmp.getParentFile(),
+ tmp.getName(), "TITLE"
+ + "\n"//
+ + "By nona"
+ + "\n" //
+ + "\n" //
+ + "Chapter 0: Resumé" + "\n" + "\n"
+ + "'sume." + "\n" + "\n"
+ + "Chapter 1: chap1" + "\n" + "\n"
+ + "Chapter fout-la-merde" + "\n"
+ + "\n"//
+ + "Fanfan." + "\n" + "\n"
+ + "Chapter 2: Chap2" + "\n" + "\n" //
+ + "Tulipe." + "\n");
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ tmp.delete();
+ }
+
+ @Override
+ public void test() throws Exception {
+ BasicSupport support = BasicSupport.getSupport(
+ SupportType.TEXT, tmp.toURI().toURL());
+
+ Story story = support.process(null);
+
+ assertEquals(2, story.getChapters().size());
+ assertEquals(1, story.getChapters().get(1)
+ .getParagraphs().size());
+ assertEquals("Tulipe.", story.getChapters().get(1)
+ .getParagraphs().get(0).getContent());
+ }
+ });
+ }
+ });
+ }
+
+ class BasicSupportParaPublic extends BasicSupportPara {
+ public BasicSupportParaPublic() {
+ super(new BasicSupportHelper(), new BasicSupportImages());
+ }
+
+ @Override
+ // and make it public!
+ public Paragraph makeParagraph(BasicSupport support, URL source,
+ String line, boolean html) {
+ return super.makeParagraph(support, source, line, html);
+ }
+
+ @Override
+ // and make it public!
+ public List<Paragraph> makeParagraphs(BasicSupport support,
+ URL source, String content, boolean html, Progress pg)
+ throws IOException {
+ return super.makeParagraphs(support, source, content, html, pg);
+ }
+
+ @Override
+ // and make it public!
+ public Paragraph processPara(String line, boolean html) {
+ return super.processPara(line, html);
+ }
+
+ @Override
+ // and make it public!
+ public List<Paragraph> requotify(Paragraph para, boolean html) {
+ return super.requotify(para, html);
+ }
+ }
+}
import be.nikiroo.utils.test.TestLauncher;
class ConversionTest extends TestLauncher {
- private File testFile;
- private File expectedDir;
- private File resultDir;
+ private String testUri;
+ private String expectedDir;
+ private String resultDir;
private List<BasicOutput.OutputType> realTypes;
private Map<String, List<String>> skipCompare;
+ private Map<String, List<String>> skipCompareCross;
- public ConversionTest(String[] args) {
- super("Conversion", args);
+ public ConversionTest(String testName, final String testUri,
+ final String expectedDir, final String resultDir, String[] args) {
+ super("Conversion - " + testName, args);
+
+ this.testUri = testUri;
+ this.expectedDir = expectedDir;
+ this.resultDir = resultDir;
// Special mode SYSOUT is not a file type (System.out)
realTypes = new ArrayList<BasicOutput.OutputType>();
}
}
- addTest(new TestCase("Read the test file") {
- @Override
- public void test() throws Exception {
- assertEquals("The test file \"" + testFile
- + "\" cannot be found", true, testFile.exists());
- }
- });
+ if (!testUri.startsWith("http://") && !testUri.startsWith("https://")) {
+ addTest(new TestCase("Read the test file") {
+ @Override
+ public void test() throws Exception {
+ assertEquals("The test file \"" + testUri
+ + "\" cannot be found", true,
+ new File(testUri).exists());
+ }
+ });
+ }
addTest(new TestCase("Assure directories exist") {
@Override
public void test() throws Exception {
- expectedDir.mkdirs();
- resultDir.mkdirs();
+ new File(expectedDir).mkdirs();
+ new File(resultDir).mkdirs();
assertEquals("The Expected directory \"" + expectedDir
- + "\" cannot be created", true, expectedDir.exists());
+ + "\" cannot be created", true,
+ new File(expectedDir).exists());
assertEquals("The Result directory \"" + resultDir
- + "\" cannot be created", true, resultDir.exists());
+ + "\" cannot be created", true,
+ new File(resultDir).exists());
}
});
@Override
protected void start() throws Exception {
- testFile = new File("test/test.story");
- expectedDir = new File("test/expected/");
- resultDir = new File("test/result/");
-
skipCompare = new HashMap<String, List<String>>();
+ skipCompareCross = new HashMap<String, List<String>>();
+
skipCompare.put("epb.ncx",
Arrays.asList(" <meta name=\"dtb:uid\" content="));
skipCompare.put("epb.opf", Arrays.asList(" <dc:subject>",
" <dc:identifier id=\"BookId\" opf:scheme=\"URI\">"));
skipCompare.put(".info",
- Arrays.asList("CREATION_DATE=", "SUBJECT=", "URL=", "UUID="));
+ Arrays.asList("CREATION_DATE=", "URL=\"file:/", "UUID="));
skipCompare.put("URL", Arrays.asList("file:/"));
+
+ for (String key : skipCompare.keySet()) {
+ skipCompareCross.put(key, skipCompare.get(key));
+ }
+
+ skipCompareCross.put(".info", Arrays.asList(""));
+ skipCompareCross.put("epb.opf", Arrays.asList(" <dc:"));
+ skipCompareCross.put("title.xhtml",
+ Arrays.asList(" <div class=\"type\">"));
+ skipCompareCross.put("index.html",
+ Arrays.asList(" <div class=\"type\">"));
+ skipCompareCross.put("URL", Arrays.asList(""));
}
@Override
return new TestCase(type + " output mode") {
@Override
public void test() throws Exception {
- File target = generate(this, testFile, resultDir, type);
+ File target = generate(this, testUri, new File(resultDir), type);
target = new File(target.getAbsolutePath()
+ type.getDefaultExtension(false));
// Check conversion:
- compareFiles(this, expectedDir, resultDir, type, "Generate "
- + type);
+ compareFiles(this, new File(expectedDir), new File(resultDir),
+ type, "Generate " + type);
// LATEX not supported as input
if (BasicOutput.OutputType.LATEX.equals(type)) {
for (BasicOutput.OutputType crossType : realTypes) {
File crossDir = Test.tempFiles
.createTempDir("cross-result");
- generate(this, target, crossDir, crossType);
- compareFiles(this, resultDir, crossDir, crossType,
- "Cross compare " + crossType + " generated from "
- + type);
+
+ generate(this, target.getAbsolutePath(), crossDir,
+ crossType);
+ compareFiles(this, new File(resultDir), crossDir,
+ crossType, "Cross compare " + crossType
+ + " generated from " + type);
}
}
};
}
- private File generate(TestCase testCase, File testFile, File resultDir,
+ private File generate(TestCase testCase, String testUri, File resultDir,
BasicOutput.OutputType type) throws Exception {
final List<String> errors = new ArrayList<String>();
try {
File target = new File(resultDir, type.toString());
- int code = Main.convert(testFile.getAbsolutePath(),
- type.toString(), target.getAbsolutePath(), false, null);
+ int code = Main.convert(testUri, type.toString(),
+ target.getAbsolutePath(), false, null);
String error = "";
for (String err : errors) {
private void compareFiles(TestCase testCase, File expectedDir,
File resultDir, final BasicOutput.OutputType limitTiFiles,
final String errMess) throws Exception {
+
+ Map<String, List<String>> skipCompare = errMess.startsWith("Cross") ? this.skipCompareCross
+ : this.skipCompare;
+
FilenameFilter filter = null;
if (limitTiFiles != null) {
filter = new FilenameFilter() {
package be.nikiroo.fanfix.test;
import java.io.File;
-import java.io.FileOutputStream;
import java.io.IOException;
-import java.util.Properties;
import be.nikiroo.fanfix.Instance;
+import be.nikiroo.fanfix.bundles.Config;
import be.nikiroo.fanfix.bundles.ConfigBundle;
import be.nikiroo.utils.IOUtils;
import be.nikiroo.utils.TempFiles;
* @author niki
*/
public class Test extends TestLauncher {
+ //
+ // 3 files can control the test:
+ // - test/VERBOSE: enable verbose mode
+ // - test/OFFLINE: to forbid any downloading
+ // - test/FORCE_REFRESH: to force a clear of the cache
+ //
+ // The test files will be:
+ // - test/*.url: URL to download in text format, content = URL
+ // - test/*.story: text mode story, content = story
+ //
+
/**
* The temporary files handler.
*/
* @param args
* the arguments to configure the number of columns and the ok/ko
* {@link String}s
+ *
+ * @throws IOException
*/
- public Test(String[] args) {
+ public Test(String[] args) throws IOException {
super("Fanfix", args);
Instance.setTraceHandler(null);
- addSeries(new BasicSupportTest(args));
+ addSeries(new BasicSupportUtilitiesTest(args));
+ addSeries(new BasicSupportDeprecatedTest(args));
addSeries(new LibraryTest(args));
- addSeries(new ConversionTest(args));
+
+ File sources = new File("test/");
+ if (sources.isDirectory()) {
+ for (File file : sources.listFiles()) {
+ if (file.isDirectory()) {
+ continue;
+ }
+
+ String expectedDir = new File(file.getParentFile(), "expected_"
+ + file.getName()).getAbsolutePath();
+ String resultDir = new File(file.getParentFile(), "result_"
+ + file.getName()).getAbsolutePath();
+
+ String uri;
+ if (file.getName().endsWith(".url")) {
+ uri = IOUtils.readSmallFile(file).trim();
+ } else if (file.getName().endsWith(".story")) {
+ uri = file.getAbsolutePath();
+ } else {
+ continue;
+ }
+
+ addSeries(new ConversionTest(file.getName(), uri, expectedDir,
+ resultDir, args));
+ }
+ }
}
/**
* in case of I/O error
*/
static public void main(String[] args) throws IOException {
+ Instance.init();
+
+ // Verbose mode:
+ boolean verbose = new File("test/VERBOSE").exists();
+
+ // Can force refresh
+ boolean forceRefresh = new File("test/FORCE_REFRESH").exists();
+
+ // Only download files if allowed:
+ boolean offline = new File("test/OFFLINE").exists();
+ Instance.getCache().setOffline(offline);
+
int result = 0;
tempFiles = new TempFiles("fanfix-test");
try {
File tmpConfig = tempFiles.createTempDir("fanfix-config");
- File tmpCache = tempFiles.createTempDir("fanfix-cache");
-
- FileOutputStream out = null;
- try {
- out = new FileOutputStream(new File(tmpConfig,
- "config.properties"));
- Properties props = new Properties();
- props.setProperty("CACHE_DIR", tmpCache.getAbsolutePath());
- props.store(out, null);
- } finally {
- if (out != null) {
- out.close();
- }
+ File localCache = new File("test/CACHE");
+ if (forceRefresh) {
+ IOUtils.deltree(localCache);
}
+ localCache.mkdirs();
ConfigBundle config = new ConfigBundle();
Bundles.setDirectory(tmpConfig.getAbsolutePath());
+ config.setString(Config.CACHE_DIR, localCache.getAbsolutePath());
+ config.setInteger(Config.CACHE_MAX_TIME_STABLE, -1);
+ config.setInteger(Config.CACHE_MAX_TIME_CHANGING, -1);
config.updateFile(tmpConfig.getPath());
-
System.setProperty("CONFIG_DIR", tmpConfig.getAbsolutePath());
- result = new Test(args).launch();
+ Instance.init(true);
+ Instance.getCache().setOffline(offline);
+
+ TestLauncher tests = new Test(args);
+ tests.setDetails(verbose);
+
+ result = tests.launch();
IOUtils.deltree(tmpConfig);
- IOUtils.deltree(tmpCache);
} finally {
// Test temp files
tempFiles.close();