Merge branch 'master' into subtree
[fanfix.git] / supported / BasicSupportHelper.java
CommitLineData
0ffa4754
NR
1package be.nikiroo.fanfix.supported;
2
3import java.io.File;
4import java.io.IOException;
5import java.io.InputStream;
6import java.net.MalformedURLException;
7import java.net.URL;
bff19b54
NR
8import java.text.ParseException;
9import java.text.SimpleDateFormat;
10import java.util.Date;
0ffa4754
NR
11
12import be.nikiroo.fanfix.Instance;
13import be.nikiroo.fanfix.bundles.Config;
14import be.nikiroo.utils.Image;
bff19b54 15import be.nikiroo.utils.StringUtils;
0ffa4754
NR
16
17/**
18 * Helper class for {@link BasicSupport}, mostly dedicated to text formating for
19 * the classes that implement {@link BasicSupport}.
20 *
21 * @author niki
22 */
8d59ce07 23public class BasicSupportHelper {
0ffa4754
NR
24 /**
25 * Get the default cover related to this subject (see <tt>.info</tt> files).
26 *
27 * @param subject
28 * the subject
29 *
30 * @return the cover if any, or NULL
31 */
8d59ce07 32 public Image getDefaultCover(String subject) {
d66deb8d 33 if (subject != null && !subject.isEmpty() && Instance.getInstance().getCoverDir() != null) {
0ffa4754 34 try {
d66deb8d 35 File fileCover = new File(Instance.getInstance().getCoverDir(), subject);
0ffa4754
NR
36 return getImage(null, fileCover.toURI().toURL(), subject);
37 } catch (MalformedURLException e) {
38 }
39 }
40
41 return null;
42 }
43
44 /**
45 * Return the list of supported image extensions.
46 *
47 * @param emptyAllowed
48 * TRUE to allow an empty extension on first place, which can be
49 * used when you may already have an extension in your input but
50 * are not sure about it
51 *
52 * @return the extensions
53 */
8d59ce07 54 public String[] getImageExt(boolean emptyAllowed) {
0ffa4754
NR
55 if (emptyAllowed) {
56 return new String[] { "", ".png", ".jpg", ".jpeg", ".gif", ".bmp" };
57 }
58
59 return new String[] { ".png", ".jpg", ".jpeg", ".gif", ".bmp" };
60 }
61
62 /**
63 * Check if the given resource can be a local image or a remote image, then
64 * refresh the cache with it if it is.
65 *
66 * @param support
8d59ce07 67 * the linked {@link BasicSupport} (can be NULL)
0ffa4754 68 * @param source
4642806a
NR
69 * the source of the story (for image lookup in the same path if
70 * the source is a file, can be NULL)
0ffa4754
NR
71 * @param line
72 * the resource to check
73 *
74 * @return the image if found, or NULL
75 *
76 */
8d59ce07 77 public Image getImage(BasicSupport support, URL source, String line) {
0ffa4754
NR
78 URL url = getImageUrl(support, source, line);
79 if (url != null) {
80 if ("file".equals(url.getProtocol())) {
81 if (new File(url.getPath()).isDirectory()) {
82 return null;
83 }
84 }
85 InputStream in = null;
86 try {
d66deb8d 87 in = Instance.getInstance().getCache().open(url, support, true);
002972e9
NR
88 Image img = new Image(in);
89 if (img.getSize() == 0) {
90 img.close();
91 throw new IOException(
92 "Empty image not accepted");
93 }
94 return img;
0ffa4754
NR
95 } catch (IOException e) {
96 } finally {
97 if (in != null) {
98 try {
99 in.close();
100 } catch (IOException e) {
101 }
102 }
103 }
104 }
105
106 return null;
107 }
108
109 /**
110 * Check if the given resource can be a local image or a remote image, then
111 * refresh the cache with it if it is.
112 *
113 * @param support
8d59ce07 114 * the linked {@link BasicSupport} (can be NULL)
0ffa4754 115 * @param source
4642806a
NR
116 * the source of the story (for image lookup in the same path if
117 * the source is a file, can be NULL)
0ffa4754
NR
118 * @param line
119 * the resource to check
120 *
121 * @return the image URL if found, or NULL
122 *
123 */
8d59ce07 124 public URL getImageUrl(BasicSupport support, URL source, String line) {
0ffa4754
NR
125 URL url = null;
126
127 if (line != null) {
128 // try for files
129 if (source != null) {
130 try {
131
132 String relPath = null;
133 String absPath = null;
134 try {
135 String path = new File(source.getFile()).getParent();
136 relPath = new File(new File(path), line.trim())
137 .getAbsolutePath();
138 } catch (Exception e) {
139 // Cannot be converted to path (one possibility to take
140 // into account: absolute path on Windows)
141 }
142 try {
143 absPath = new File(line.trim()).getAbsolutePath();
144 } catch (Exception e) {
145 // Cannot be converted to path (at all)
146 }
147
148 for (String ext : getImageExt(true)) {
149 File absFile = new File(absPath + ext);
150 File relFile = new File(relPath + ext);
151 if (absPath != null && absFile.exists()
152 && absFile.isFile()) {
153 url = absFile.toURI().toURL();
154 } else if (relPath != null && relFile.exists()
155 && relFile.isFile()) {
156 url = relFile.toURI().toURL();
157 }
158 }
159 } catch (Exception e) {
160 // Should not happen since we control the correct arguments
161 }
162 }
163
164 if (url == null) {
165 // try for URLs
166 try {
167 for (String ext : getImageExt(true)) {
d66deb8d 168 if (Instance.getInstance().getCache().check(new URL(line + ext), true)) {
0ffa4754
NR
169 url = new URL(line + ext);
170 break;
171 }
172 }
173
174 // try out of cache
175 if (url == null) {
176 for (String ext : getImageExt(true)) {
177 try {
178 url = new URL(line + ext);
d66deb8d 179 Instance.getInstance().getCache().refresh(url, support, true);
0ffa4754
NR
180 break;
181 } catch (IOException e) {
182 // no image with this ext
183 url = null;
184 }
185 }
186 }
187 } catch (MalformedURLException e) {
188 // Not an url
189 }
190 }
191
192 // refresh the cached file
193 if (url != null) {
194 try {
d66deb8d 195 Instance.getInstance().getCache().refresh(url, support, true);
0ffa4754
NR
196 } catch (IOException e) {
197 // woops, broken image
198 url = null;
199 }
200 }
201 }
202
203 return url;
204 }
205
206 /**
207 * Fix the author name if it is prefixed with some "by" {@link String}.
208 *
209 * @param author
210 * the author with a possible prefix
211 *
212 * @return the author without prefixes
213 */
8d59ce07 214 public String fixAuthor(String author) {
0ffa4754
NR
215 if (author != null) {
216 for (String suffix : new String[] { " ", ":" }) {
d66deb8d 217 for (String byString : Instance.getInstance().getConfig().getList(Config.CONF_BYS)) {
0ffa4754
NR
218 byString += suffix;
219 if (author.toUpperCase().startsWith(byString.toUpperCase())) {
220 author = author.substring(byString.length()).trim();
221 }
222 }
223 }
224
225 // Special case (without suffix):
226 if (author.startsWith("©")) {
227 author = author.substring(1);
228 }
229 }
230
231 return author;
232 }
bff19b54
NR
233
234 /**
235 * Try to convert the date to a known, fixed format.
236 * <p>
237 * If it fails to do so, it will return the date as-is.
238 *
239 * @param date
240 * the date to convert
241 *
242 * @return the converted date, or the date as-is
243 */
244 public String formatDate(String date) {
245 long ms = 0;
246
247 if (date != null && !date.isEmpty()) {
248 // Default Fanfix format:
249 try {
250 ms = StringUtils.toTime(date);
251 } catch (ParseException e) {
252 }
253
254 // Second chance:
255 if (ms <= 0) {
256 SimpleDateFormat sdf = new SimpleDateFormat(
257 "yyyy-MM-dd'T'HH:mm:ssSSS");
258 try {
259 ms = sdf.parse(date).getTime();
260 } catch (ParseException e) {
261 }
262 }
263
264 // Last chance:
265 if (ms <= 0 && date.length() >= 10) {
266 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
267 try {
268 ms = sdf.parse(date.substring(0, 10)).getTime();
269 } catch (ParseException e) {
270 }
271 }
272
273 // If we found something, use THIS format:
274 if (ms > 0) {
275 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
276 return sdf.format(new Date(ms));
277 }
278 }
279
280 if (date == null) {
281 date = "";
282 }
283
284 // :(
285 return date;
286 }
0ffa4754 287}