1 package be
.nikiroo
.fanfix
.supported
;
4 import java
.io
.FileInputStream
;
5 import java
.io
.FileNotFoundException
;
6 import java
.io
.IOException
;
7 import java
.io
.InputStream
;
9 import java
.util
.ArrayList
;
10 import java
.util
.List
;
11 import java
.util
.Scanner
;
13 import be
.nikiroo
.fanfix
.Instance
;
14 import be
.nikiroo
.fanfix
.bundles
.Config
;
15 import be
.nikiroo
.fanfix
.data
.MetaData
;
16 import be
.nikiroo
.utils
.Image
;
17 import be
.nikiroo
.utils
.MarkableFileInputStream
;
19 // not complete: no "description" tag
20 public class InfoReader
{
21 public static MetaData
readMeta(File infoFile
, boolean withCover
)
23 if (infoFile
== null) {
24 throw new IOException("File is null");
27 if (infoFile
.exists()) {
28 InputStream in
= new MarkableFileInputStream(new FileInputStream(
31 return createMeta(infoFile
.toURI().toURL(), in
, withCover
);
37 throw new FileNotFoundException(
38 "File given as argument does not exists: "
39 + infoFile
.getAbsolutePath());
42 private static MetaData
createMeta(URL sourceInfoFile
, InputStream in
,
43 boolean withCover
) throws IOException
{
44 MetaData meta
= new MetaData();
46 meta
.setTitle(getInfoTag(in
, "TITLE"));
47 meta
.setAuthor(getInfoTag(in
, "AUTHOR"));
48 meta
.setDate(getInfoTag(in
, "DATE"));
49 meta
.setTags(getInfoTagList(in
, "TAGS", ","));
50 meta
.setSource(getInfoTag(in
, "SOURCE"));
51 meta
.setUrl(getInfoTag(in
, "URL"));
52 meta
.setPublisher(getInfoTag(in
, "PUBLISHER"));
53 meta
.setUuid(getInfoTag(in
, "UUID"));
54 meta
.setLuid(getInfoTag(in
, "LUID"));
55 meta
.setLang(getInfoTag(in
, "LANG"));
56 meta
.setSubject(getInfoTag(in
, "SUBJECT"));
57 meta
.setType(getInfoTag(in
, "TYPE"));
58 meta
.setImageDocument(getInfoTagBoolean(in
, "IMAGES_DOCUMENT", false));
60 String infoTag
= getInfoTag(in
, "COVER");
61 if (infoTag
!= null && !infoTag
.trim().isEmpty()) {
62 meta
.setCover(BasicSupportHelper
.getImage(null, sourceInfoFile
,
65 if (meta
.getCover() == null) {
66 // Second chance: try to check for a cover next to the info file
67 meta
.setCover(getCoverByName(sourceInfoFile
));
71 meta
.setWords(Long
.parseLong(getInfoTag(in
, "WORDCOUNT")));
72 } catch (NumberFormatException e
) {
75 meta
.setCreationDate(getInfoTag(in
, "CREATION_DATE"));
76 meta
.setFakeCover(Boolean
.parseBoolean(getInfoTag(in
, "FAKE_COVER")));
78 if (withCover
&& meta
.getCover() == null) {
79 meta
.setCover(BasicSupportHelper
.getDefaultCover(meta
.getSubject()));
86 * Return the cover image if it is next to the source file.
88 * @param sourceInfoFile
91 * @return the cover if present, NULL if not
93 public static Image
getCoverByName(URL sourceInfoFile
) {
96 File basefile
= new File(sourceInfoFile
.getFile());
99 + Instance
.getConfig().getString(Config
.IMAGE_FORMAT_COVER
)
102 // Without removing ext
103 cover
= BasicSupportHelper
.getImage(null, sourceInfoFile
,
104 basefile
.getAbsolutePath() + ext
);
107 String name
= basefile
.getName();
108 int pos
= name
.lastIndexOf(".");
109 if (cover
== null && pos
> 0) {
110 name
= name
.substring(0, pos
);
111 basefile
= new File(basefile
.getParent(), name
);
113 cover
= BasicSupportHelper
.getImage(null, sourceInfoFile
,
114 basefile
.getAbsolutePath() + ext
);
120 private static boolean getInfoTagBoolean(InputStream in
, String key
,
121 boolean def
) throws IOException
{
122 Boolean value
= getInfoTagBoolean(in
, key
);
123 return value
== null ? def
: value
;
126 private static Boolean
getInfoTagBoolean(InputStream in
, String key
)
128 String value
= getInfoTag(in
, key
);
129 if (value
!= null && !value
.trim().isEmpty()) {
130 value
= value
.toLowerCase().trim();
131 return value
.equals("1") || value
.equals("on")
132 || value
.equals("true") || value
.equals("yes");
138 private static List
<String
> getInfoTagList(InputStream in
, String key
,
139 String separator
) throws IOException
{
140 List
<String
> list
= new ArrayList
<String
>();
141 String tt
= getInfoTag(in
, key
);
143 for (String tag
: tt
.split(separator
)) {
144 list
.add(tag
.trim());
152 * Return the value of the given tag in the <tt>.info</tt> file if present.
157 * @return the value or NULL
159 * @throws IOException
160 * in case of I/O error
162 private static String
getInfoTag(InputStream in
, String key
)
164 key
= "^" + key
+ "=";
168 String value
= getLine(in
, key
, 0);
169 if (value
!= null && !value
.isEmpty()) {
170 value
= value
.trim().substring(key
.length() - 1).trim();
171 if (value
.startsWith("'") && value
.endsWith("'")
172 || value
.startsWith("\"") && value
.endsWith("\"")) {
173 value
= value
.substring(1, value
.length() - 1).trim();
184 * Return the first line from the given input which correspond to the given
190 * a string that must be found inside the target line (also
191 * supports "^" at start to say "only if it starts with" the
193 * @param relativeLine
194 * the line to return based upon the target line position (-1 =
195 * the line before, 0 = the target line...)
199 static private String
getLine(InputStream in
, String needle
,
201 return getLine(in
, needle
, relativeLine
, true);
205 * Return a line from the given input which correspond to the given
211 * a string that must be found inside the target line (also
212 * supports "^" at start to say "only if it starts with" the
214 * @param relativeLine
215 * the line to return based upon the target line position (-1 =
216 * the line before, 0 = the target line...)
218 * takes the first result (as opposed to the last one, which will
219 * also always spend the input)
223 static private String
getLine(InputStream in
, String needle
,
224 int relativeLine
, boolean first
) {
227 List
<String
> lines
= new ArrayList
<String
>();
228 @SuppressWarnings("resource")
229 Scanner scan
= new Scanner(in
, "UTF-8");
231 scan
.useDelimiter("\\n");
232 while (scan
.hasNext()) {
233 lines
.add(scan
.next());
236 if (needle
.startsWith("^")) {
237 if (lines
.get(lines
.size() - 1).startsWith(
238 needle
.substring(1))) {
239 index
= lines
.size() - 1;
243 if (lines
.get(lines
.size() - 1).contains(needle
)) {
244 index
= lines
.size() - 1;
249 if (index
>= 0 && index
+ relativeLine
< lines
.size()) {
250 rep
= lines
.get(index
+ relativeLine
);