1 package be
.nikiroo
.fanfix
.supported
;
4 import java
.io
.FileNotFoundException
;
5 import java
.io
.IOException
;
6 import java
.io
.InputStream
;
8 import java
.util
.ArrayList
;
10 import java
.util
.Scanner
;
12 import be
.nikiroo
.fanfix
.Instance
;
13 import be
.nikiroo
.fanfix
.bundles
.Config
;
14 import be
.nikiroo
.fanfix
.data
.MetaData
;
15 import be
.nikiroo
.utils
.Image
;
16 import be
.nikiroo
.utils
.streams
.MarkableFileInputStream
;
18 // not complete: no "description" tag
19 public class InfoReader
{
20 static protected BasicSupportHelper bsHelper
= new BasicSupportHelper();
21 // static protected BasicSupportImages bsImages = new BasicSupportImages();
22 // static protected BasicSupportPara bsPara = new BasicSupportPara(new BasicSupportHelper(), new BasicSupportImages());
24 public static MetaData
readMeta(File infoFile
, boolean withCover
)
26 if (infoFile
== null) {
27 throw new IOException("File is null");
30 if (infoFile
.exists()) {
31 InputStream in
= new MarkableFileInputStream(infoFile
);
33 return createMeta(infoFile
.toURI().toURL(), in
, withCover
);
39 throw new FileNotFoundException(
40 "File given as argument does not exists: "
41 + infoFile
.getAbsolutePath());
44 private static MetaData
createMeta(URL sourceInfoFile
, InputStream in
,
45 boolean withCover
) throws IOException
{
46 MetaData meta
= new MetaData();
48 meta
.setTitle(getInfoTag(in
, "TITLE"));
49 meta
.setAuthor(getInfoTag(in
, "AUTHOR"));
50 meta
.setDate(getInfoTag(in
, "DATE"));
51 meta
.setTags(getInfoTagList(in
, "TAGS", ","));
52 meta
.setSource(getInfoTag(in
, "SOURCE"));
53 meta
.setUrl(getInfoTag(in
, "URL"));
54 meta
.setPublisher(getInfoTag(in
, "PUBLISHER"));
55 meta
.setUuid(getInfoTag(in
, "UUID"));
56 meta
.setLuid(getInfoTag(in
, "LUID"));
57 meta
.setLang(getInfoTag(in
, "LANG"));
58 meta
.setSubject(getInfoTag(in
, "SUBJECT"));
59 meta
.setType(getInfoTag(in
, "TYPE"));
60 meta
.setImageDocument(getInfoTagBoolean(in
, "IMAGES_DOCUMENT", false));
62 String infoTag
= getInfoTag(in
, "COVER");
63 if (infoTag
!= null && !infoTag
.trim().isEmpty()) {
64 meta
.setCover(bsHelper
.getImage(null, sourceInfoFile
,
67 if (meta
.getCover() == null) {
68 // Second chance: try to check for a cover next to the info file
69 meta
.setCover(getCoverByName(sourceInfoFile
));
73 meta
.setWords(Long
.parseLong(getInfoTag(in
, "WORDCOUNT")));
74 } catch (NumberFormatException e
) {
77 meta
.setCreationDate(getInfoTag(in
, "CREATION_DATE"));
78 meta
.setFakeCover(Boolean
.parseBoolean(getInfoTag(in
, "FAKE_COVER")));
80 if (withCover
&& meta
.getCover() == null) {
81 meta
.setCover(bsHelper
.getDefaultCover(meta
.getSubject()));
88 * Return the cover image if it is next to the source file.
90 * @param sourceInfoFile
93 * @return the cover if present, NULL if not
95 public static Image
getCoverByName(URL sourceInfoFile
) {
98 File basefile
= new File(sourceInfoFile
.getFile());
101 + Instance
.getConfig().getString(Config
.FILE_FORMAT_IMAGE_FORMAT_COVER
)
104 // Without removing ext
105 cover
= bsHelper
.getImage(null, sourceInfoFile
,
106 basefile
.getAbsolutePath() + ext
);
109 String name
= basefile
.getName();
110 int pos
= name
.lastIndexOf(".");
111 if (cover
== null && pos
> 0) {
112 name
= name
.substring(0, pos
);
113 basefile
= new File(basefile
.getParent(), name
);
115 cover
= bsHelper
.getImage(null, sourceInfoFile
,
116 basefile
.getAbsolutePath() + ext
);
122 private static boolean getInfoTagBoolean(InputStream in
, String key
,
123 boolean def
) throws IOException
{
124 Boolean value
= getInfoTagBoolean(in
, key
);
125 return value
== null ? def
: value
;
128 private static Boolean
getInfoTagBoolean(InputStream in
, String key
)
130 String value
= getInfoTag(in
, key
);
131 if (value
!= null && !value
.trim().isEmpty()) {
132 value
= value
.toLowerCase().trim();
133 return value
.equals("1") || value
.equals("on")
134 || value
.equals("true") || value
.equals("yes");
140 private static List
<String
> getInfoTagList(InputStream in
, String key
,
141 String separator
) throws IOException
{
142 List
<String
> list
= new ArrayList
<String
>();
143 String tt
= getInfoTag(in
, key
);
145 for (String tag
: tt
.split(separator
)) {
146 list
.add(tag
.trim());
154 * Return the value of the given tag in the <tt>.info</tt> file if present.
159 * @return the value or NULL
161 * @throws IOException
162 * in case of I/O error
164 private static String
getInfoTag(InputStream in
, String key
)
166 key
= "^" + key
+ "=";
170 String value
= getLine(in
, key
, 0);
171 if (value
!= null && !value
.isEmpty()) {
172 value
= value
.trim().substring(key
.length() - 1).trim();
173 if (value
.startsWith("'") && value
.endsWith("'")
174 || value
.startsWith("\"") && value
.endsWith("\"")) {
175 value
= value
.substring(1, value
.length() - 1).trim();
186 * Return the first line from the given input which correspond to the given
192 * a string that must be found inside the target line (also
193 * supports "^" at start to say "only if it starts with" the
195 * @param relativeLine
196 * the line to return based upon the target line position (-1 =
197 * the line before, 0 = the target line...)
201 static private String
getLine(InputStream in
, String needle
,
203 return getLine(in
, needle
, relativeLine
, true);
207 * Return a line from the given input which correspond to the given
213 * a string that must be found inside the target line (also
214 * supports "^" at start to say "only if it starts with" the
216 * @param relativeLine
217 * the line to return based upon the target line position (-1 =
218 * the line before, 0 = the target line...)
220 * takes the first result (as opposed to the last one, which will
221 * also always spend the input)
225 static private String
getLine(InputStream in
, String needle
,
226 int relativeLine
, boolean first
) {
229 List
<String
> lines
= new ArrayList
<String
>();
230 @SuppressWarnings("resource")
231 Scanner scan
= new Scanner(in
, "UTF-8");
233 scan
.useDelimiter("\\n");
234 while (scan
.hasNext()) {
235 lines
.add(scan
.next());
238 if (needle
.startsWith("^")) {
239 if (lines
.get(lines
.size() - 1).startsWith(
240 needle
.substring(1))) {
241 index
= lines
.size() - 1;
245 if (lines
.get(lines
.size() - 1).contains(needle
)) {
246 index
= lines
.size() - 1;
251 if (index
>= 0 && index
+ relativeLine
< lines
.size()) {
252 rep
= lines
.get(index
+ relativeLine
);