tests: fix NPE, add BasicSupportUtilities tests
[nikiroo-utils.git] / src / be / nikiroo / fanfix / supported / InfoReader.java
index f84f01b27ec721c971e2dfb18381be57fcaa3df9..c22dbd711bedca99d1bde9f08400ba8e83b069b7 100644 (file)
@@ -1,40 +1,48 @@
 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;
+import java.net.URL;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Scanner;
 
+import be.nikiroo.fanfix.Instance;
+import be.nikiroo.fanfix.bundles.Config;
 import be.nikiroo.fanfix.data.MetaData;
-import be.nikiroo.utils.MarkableFileInputStream;
+import be.nikiroo.utils.Image;
+import be.nikiroo.utils.streams.MarkableFileInputStream;
 
 // not complete: no "description" tag
 public class InfoReader {
-       public static MetaData readMeta(File infoFile) throws IOException {
+       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) {
                        throw new IOException("File is null");
                }
 
                if (infoFile.exists()) {
-                       InputStream in = new MarkableFileInputStream(new FileInputStream(
-                                       infoFile));
+                       InputStream in = new MarkableFileInputStream(infoFile);
                        try {
-                               return createMeta(in);
+                               return createMeta(infoFile.toURI().toURL(), in, withCover);
                        } finally {
                                in.close();
-                               in = null;
                        }
-               } else {
-                       throw new FileNotFoundException(
-                                       "File given as argument does not exists: "
-                                                       + infoFile.getAbsolutePath());
                }
+
+               throw new FileNotFoundException(
+                               "File given as argument does not exists: "
+                                               + infoFile.getAbsolutePath());
        }
 
-       private static MetaData createMeta(InputStream in) throws IOException {
+       private static MetaData createMeta(URL sourceInfoFile, InputStream in,
+                       boolean withCover) throws IOException {
                MetaData meta = new MetaData();
 
                meta.setTitle(getInfoTag(in, "TITLE"));
@@ -50,15 +58,67 @@ public class InfoReader {
                meta.setSubject(getInfoTag(in, "SUBJECT"));
                meta.setType(getInfoTag(in, "TYPE"));
                meta.setImageDocument(getInfoTagBoolean(in, "IMAGES_DOCUMENT", false));
-               meta.setCover(BasicSupport.getImage(null, getInfoTag(in, "COVER")));
+               if (withCover) {
+                       String infoTag = getInfoTag(in, "COVER");
+                       if (infoTag != null && !infoTag.trim().isEmpty()) {
+                               meta.setCover(bsHelper.getImage(null, sourceInfoFile,
+                                               infoTag));
+                       }
+                       if (meta.getCover() == null) {
+                               // Second chance: try to check for a cover next to the info file
+                               meta.setCover(getCoverByName(sourceInfoFile));
+                       }
+               }
+               try {
+                       meta.setWords(Long.parseLong(getInfoTag(in, "WORDCOUNT")));
+               } catch (NumberFormatException e) {
+                       meta.setWords(0);
+               }
+               meta.setCreationDate(getInfoTag(in, "CREATION_DATE"));
+               meta.setFakeCover(Boolean.parseBoolean(getInfoTag(in, "FAKE_COVER")));
 
-               if (meta.getCover() == null) {
-                       meta.setCover(BasicSupport.getDefaultCover(meta.getSubject()));
+               if (withCover && meta.getCover() == null) {
+                       meta.setCover(bsHelper.getDefaultCover(meta.getSubject()));
                }
 
                return meta;
        }
 
+       /**
+        * Return the cover image if it is next to the source file.
+        * 
+        * @param sourceInfoFile
+        *            the source file
+        * 
+        * @return the cover if present, NULL if not
+        */
+       public static Image getCoverByName(URL sourceInfoFile) {
+               Image cover = null;
+
+               File basefile = new File(sourceInfoFile.getFile());
+
+               String ext = "."
+                               + Instance.getConfig().getString(Config.FILE_FORMAT_IMAGE_FORMAT_COVER)
+                                               .toLowerCase();
+
+               // Without removing ext
+               cover = bsHelper.getImage(null, sourceInfoFile,
+                               basefile.getAbsolutePath() + ext);
+
+               // Try without ext
+               String name = basefile.getName();
+               int pos = name.lastIndexOf(".");
+               if (cover == null && pos > 0) {
+                       name = name.substring(0, pos);
+                       basefile = new File(basefile.getParent(), name);
+
+                       cover = bsHelper.getImage(null, sourceInfoFile,
+                                       basefile.getAbsolutePath() + ext);
+               }
+
+               return cover;
+       }
+
        private static boolean getInfoTagBoolean(InputStream in, String key,
                        boolean def) throws IOException {
                Boolean value = getInfoTagBoolean(in, key);
@@ -107,7 +167,7 @@ public class InfoReader {
 
                if (in != null) {
                        in.reset();
-                       String value = BasicSupport.getLine(in, key, 0);
+                       String value = getLine(in, key, 0);
                        if (value != null && !value.isEmpty()) {
                                value = value.trim().substring(key.length() - 1).trim();
                                if (value.startsWith("'") && value.endsWith("'")
@@ -121,4 +181,81 @@ public class InfoReader {
 
                return null;
        }
+
+       /**
+        * Return the first line from the given input which correspond to the given
+        * selectors.
+        * 
+        * @param in
+        *            the input
+        * @param needle
+        *            a string that must be found inside the target line (also
+        *            supports "^" at start to say "only if it starts with" the
+        *            needle)
+        * @param relativeLine
+        *            the line to return based upon the target line position (-1 =
+        *            the line before, 0 = the target line...)
+        * 
+        * @return the line
+        */
+       static private String getLine(InputStream in, String needle,
+                       int relativeLine) {
+               return getLine(in, needle, relativeLine, true);
+       }
+
+       /**
+        * Return a line from the given input which correspond to the given
+        * selectors.
+        * 
+        * @param in
+        *            the input
+        * @param needle
+        *            a string that must be found inside the target line (also
+        *            supports "^" at start to say "only if it starts with" the
+        *            needle)
+        * @param relativeLine
+        *            the line to return based upon the target line position (-1 =
+        *            the line before, 0 = the target line...)
+        * @param first
+        *            takes the first result (as opposed to the last one, which will
+        *            also always spend the input)
+        * 
+        * @return the line
+        */
+       static private String getLine(InputStream in, String needle,
+                       int relativeLine, boolean first) {
+               String rep = null;
+
+               List<String> lines = new ArrayList<String>();
+               @SuppressWarnings("resource")
+               Scanner scan = new Scanner(in, "UTF-8");
+               int index = -1;
+               scan.useDelimiter("\\n");
+               while (scan.hasNext()) {
+                       lines.add(scan.next());
+
+                       if (index == -1) {
+                               if (needle.startsWith("^")) {
+                                       if (lines.get(lines.size() - 1).startsWith(
+                                                       needle.substring(1))) {
+                                               index = lines.size() - 1;
+                                       }
+
+                               } else {
+                                       if (lines.get(lines.size() - 1).contains(needle)) {
+                                               index = lines.size() - 1;
+                                       }
+                               }
+                       }
+
+                       if (index >= 0 && index + relativeLine < lines.size()) {
+                               rep = lines.get(index + relativeLine);
+                               if (first) {
+                                       break;
+                               }
+                       }
+               }
+
+               return rep;
+       }
 }