try +1
[fanfix.git] / src / be / nikiroo / fanfix / supported / InfoReader.java
CommitLineData
68686a37
NR
1package be.nikiroo.fanfix.supported;
2
3import java.io.File;
4import java.io.FileInputStream;
5import java.io.FileNotFoundException;
6import java.io.IOException;
7import java.io.InputStream;
333f0e7b 8import java.net.URL;
68686a37
NR
9import java.util.ArrayList;
10import java.util.List;
7445f856 11import java.util.Scanner;
68686a37 12
2d2a3222
NR
13import be.nikiroo.fanfix.Instance;
14import be.nikiroo.fanfix.bundles.Config;
68686a37
NR
15import be.nikiroo.fanfix.data.MetaData;
16import be.nikiroo.utils.MarkableFileInputStream;
17
18// not complete: no "description" tag
19public class InfoReader {
57f02339
NR
20 public static MetaData readMeta(File infoFile, boolean withCover)
21 throws IOException {
68686a37
NR
22 if (infoFile == null) {
23 throw new IOException("File is null");
24 }
25
26 if (infoFile.exists()) {
27 InputStream in = new MarkableFileInputStream(new FileInputStream(
28 infoFile));
29 try {
57f02339 30 return createMeta(infoFile.toURI().toURL(), in, withCover);
68686a37
NR
31 } finally {
32 in.close();
68686a37 33 }
68686a37 34 }
211f7ddb
NR
35
36 throw new FileNotFoundException(
37 "File given as argument does not exists: "
38 + infoFile.getAbsolutePath());
68686a37
NR
39 }
40
57f02339
NR
41 private static MetaData createMeta(URL sourceInfoFile, InputStream in,
42 boolean withCover) throws IOException {
68686a37
NR
43 MetaData meta = new MetaData();
44
45 meta.setTitle(getInfoTag(in, "TITLE"));
46 meta.setAuthor(getInfoTag(in, "AUTHOR"));
47 meta.setDate(getInfoTag(in, "DATE"));
48 meta.setTags(getInfoTagList(in, "TAGS", ","));
49 meta.setSource(getInfoTag(in, "SOURCE"));
2206ef66 50 meta.setUrl(getInfoTag(in, "URL"));
68686a37
NR
51 meta.setPublisher(getInfoTag(in, "PUBLISHER"));
52 meta.setUuid(getInfoTag(in, "UUID"));
53 meta.setLuid(getInfoTag(in, "LUID"));
54 meta.setLang(getInfoTag(in, "LANG"));
55 meta.setSubject(getInfoTag(in, "SUBJECT"));
56 meta.setType(getInfoTag(in, "TYPE"));
57 meta.setImageDocument(getInfoTagBoolean(in, "IMAGES_DOCUMENT", false));
57f02339 58 if (withCover) {
16a81ef7
NR
59 String infoTag = getInfoTag(in, "COVER");
60 if (infoTag != null && !infoTag.trim().isEmpty()) {
0ffa4754 61 meta.setCover(BasicSupportHelper.getImage(null, sourceInfoFile,
16a81ef7
NR
62 infoTag));
63 }
2d2a3222
NR
64 // Second chance: try to check for a cover next to the info file
65 if (meta.getCover() == null) {
66 String info = sourceInfoFile.getFile().toString();
67 if (info.endsWith(".info")) {
68 info = info.substring(0, info.length() - ".info".length());
69 String ext = "."
2a25f781
NR
70 + Instance.getConfig()
71 .getString(Config.IMAGE_FORMAT_COVER)
72 .toLowerCase();
0ffa4754
NR
73 meta.setCover(BasicSupportHelper.getImage(null,
74 sourceInfoFile, info + ext));
2d2a3222
NR
75 }
76 }
57f02339 77 }
793f1071
NR
78 try {
79 meta.setWords(Long.parseLong(getInfoTag(in, "WORDCOUNT")));
80 } catch (NumberFormatException e) {
81 meta.setWords(0);
82 }
83 meta.setCreationDate(getInfoTag(in, "CREATION_DATE"));
a9eb3f46 84 meta.setFakeCover(Boolean.parseBoolean(getInfoTag(in, "FAKE_COVER")));
68686a37 85
57f02339 86 if (withCover && meta.getCover() == null) {
0ffa4754 87 meta.setCover(BasicSupportHelper.getDefaultCover(meta.getSubject()));
68686a37
NR
88 }
89
90 return meta;
91 }
92
93 private static boolean getInfoTagBoolean(InputStream in, String key,
94 boolean def) throws IOException {
95 Boolean value = getInfoTagBoolean(in, key);
96 return value == null ? def : value;
97 }
98
99 private static Boolean getInfoTagBoolean(InputStream in, String key)
100 throws IOException {
101 String value = getInfoTag(in, key);
102 if (value != null && !value.trim().isEmpty()) {
103 value = value.toLowerCase().trim();
104 return value.equals("1") || value.equals("on")
105 || value.equals("true") || value.equals("yes");
106 }
107
108 return null;
109 }
110
111 private static List<String> getInfoTagList(InputStream in, String key,
112 String separator) throws IOException {
113 List<String> list = new ArrayList<String>();
114 String tt = getInfoTag(in, key);
115 if (tt != null) {
116 for (String tag : tt.split(separator)) {
117 list.add(tag.trim());
118 }
119 }
120
121 return list;
122 }
123
124 /**
125 * Return the value of the given tag in the <tt>.info</tt> file if present.
126 *
127 * @param key
128 * the tag key
129 *
130 * @return the value or NULL
131 *
132 * @throws IOException
133 * in case of I/O error
134 */
135 private static String getInfoTag(InputStream in, String key)
136 throws IOException {
137 key = "^" + key + "=";
138
139 if (in != null) {
140 in.reset();
7445f856 141 String value = getLine(in, key, 0);
68686a37
NR
142 if (value != null && !value.isEmpty()) {
143 value = value.trim().substring(key.length() - 1).trim();
144 if (value.startsWith("'") && value.endsWith("'")
145 || value.startsWith("\"") && value.endsWith("\"")) {
146 value = value.substring(1, value.length() - 1).trim();
147 }
148
149 return value;
150 }
151 }
152
153 return null;
154 }
7445f856
NR
155
156 /**
157 * Return the first line from the given input which correspond to the given
158 * selectors.
159 *
160 * @param in
161 * the input
162 * @param needle
163 * a string that must be found inside the target line (also
164 * supports "^" at start to say "only if it starts with" the
165 * needle)
166 * @param relativeLine
167 * the line to return based upon the target line position (-1 =
168 * the line before, 0 = the target line...)
169 *
170 * @return the line
171 */
172 static private String getLine(InputStream in, String needle,
173 int relativeLine) {
174 return getLine(in, needle, relativeLine, true);
175 }
176
177 /**
178 * Return a line from the given input which correspond to the given
179 * selectors.
180 *
181 * @param in
182 * the input
183 * @param needle
184 * a string that must be found inside the target line (also
185 * supports "^" at start to say "only if it starts with" the
186 * needle)
187 * @param relativeLine
188 * the line to return based upon the target line position (-1 =
189 * the line before, 0 = the target line...)
190 * @param first
191 * takes the first result (as opposed to the last one, which will
192 * also always spend the input)
193 *
194 * @return the line
195 */
196 static private String getLine(InputStream in, String needle,
197 int relativeLine, boolean first) {
198 String rep = null;
199
200 List<String> lines = new ArrayList<String>();
201 @SuppressWarnings("resource")
202 Scanner scan = new Scanner(in, "UTF-8");
203 int index = -1;
204 scan.useDelimiter("\\n");
205 while (scan.hasNext()) {
206 lines.add(scan.next());
207
208 if (index == -1) {
209 if (needle.startsWith("^")) {
210 if (lines.get(lines.size() - 1).startsWith(
211 needle.substring(1))) {
212 index = lines.size() - 1;
213 }
214
215 } else {
216 if (lines.get(lines.size() - 1).contains(needle)) {
217 index = lines.size() - 1;
218 }
219 }
220 }
221
222 if (index >= 0 && index + relativeLine < lines.size()) {
223 rep = lines.get(index + relativeLine);
224 if (first) {
225 break;
226 }
227 }
228 }
229
230 return rep;
231 }
68686a37 232}