test: improve flag files
[nikiroo-utils.git] / src / be / nikiroo / fanfix / library / CacheLibrary.java
1 package be.nikiroo.fanfix.library;
2
3 import java.io.File;
4 import java.io.IOException;
5 import java.net.URL;
6 import java.util.List;
7
8 import be.nikiroo.fanfix.Instance;
9 import be.nikiroo.fanfix.bundles.UiConfig;
10 import be.nikiroo.fanfix.data.MetaData;
11 import be.nikiroo.fanfix.data.Story;
12 import be.nikiroo.utils.Image;
13 import be.nikiroo.utils.Progress;
14
15 /**
16 * This library will cache another pre-existing {@link BasicLibrary}.
17 *
18 * @author niki
19 */
20 public class CacheLibrary extends BasicLibrary {
21 private List<MetaData> metas;
22 private BasicLibrary lib;
23 private LocalLibrary cacheLib;
24
25 /**
26 * Create a cache library around the given one.
27 * <p>
28 * It will return the same result, but those will be saved to disk at the
29 * same time to be fetched quicker the next time.
30 *
31 * @param cacheDir
32 * the cache directory where to save the files to disk
33 * @param lib
34 * the original library to wrap
35 */
36 public CacheLibrary(File cacheDir, BasicLibrary lib) {
37 this.cacheLib = new LocalLibrary(cacheDir, Instance.getUiConfig()
38 .getString(UiConfig.GUI_NON_IMAGES_DOCUMENT_TYPE), Instance
39 .getUiConfig().getString(UiConfig.GUI_IMAGES_DOCUMENT_TYPE),
40 true);
41 this.lib = lib;
42 }
43
44 @Override
45 public String getLibraryName() {
46 return lib.getLibraryName();
47 }
48
49 @Override
50 public Status getStatus() {
51 return lib.getStatus();
52 }
53
54 @Override
55 protected List<MetaData> getMetas(Progress pg) throws IOException {
56 if (pg == null) {
57 pg = new Progress();
58 }
59
60 if (metas == null) {
61 metas = lib.getMetas(pg);
62 }
63
64 pg.done();
65 return metas;
66 }
67
68 @Override
69 public synchronized MetaData getInfo(String luid) throws IOException {
70 MetaData info = cacheLib.getInfo(luid);
71 if (info == null) {
72 info = lib.getInfo(luid);
73 }
74
75 return info;
76 }
77
78 @Override
79 public synchronized Story getStory(String luid, MetaData meta, Progress pg)
80 throws IOException {
81 if (pg == null) {
82 pg = new Progress();
83 }
84
85 Progress pgImport = new Progress();
86 Progress pgGet = new Progress();
87
88 pg.setMinMax(0, 4);
89 pg.addProgress(pgImport, 3);
90 pg.addProgress(pgGet, 1);
91
92 if (!isCached(luid)) {
93 try {
94 cacheLib.imprt(lib, luid, pgImport);
95 updateInfo(cacheLib.getInfo(luid));
96 pgImport.done();
97 } catch (IOException e) {
98 Instance.getTraceHandler().error(e);
99 }
100
101 pgImport.done();
102 pgGet.done();
103 }
104
105 String type = cacheLib.getOutputType(meta.isImageDocument());
106 MetaData cachedMeta = meta.clone();
107 cachedMeta.setType(type);
108
109 return cacheLib.getStory(luid, cachedMeta, pg);
110 }
111
112 @Override
113 public synchronized File getFile(final String luid, Progress pg)
114 throws IOException {
115 if (pg == null) {
116 pg = new Progress();
117 }
118
119 Progress pgGet = new Progress();
120 Progress pgRecall = new Progress();
121
122 pg.setMinMax(0, 5);
123 pg.addProgress(pgGet, 4);
124 pg.addProgress(pgRecall, 1);
125
126 if (!isCached(luid)) {
127 getStory(luid, pgGet);
128 pgGet.done();
129 }
130
131 File file = cacheLib.getFile(luid, pgRecall);
132 pgRecall.done();
133
134 pg.done();
135 return file;
136 }
137
138 @Override
139 public Image getCover(final String luid) throws IOException {
140 if (isCached(luid)) {
141 return cacheLib.getCover(luid);
142 }
143
144 // We could update the cache here, but it's not easy
145 return lib.getCover(luid);
146 }
147
148 @Override
149 public Image getSourceCover(String source) throws IOException {
150 Image custom = getCustomSourceCover(source);
151 if (custom != null) {
152 return custom;
153 }
154
155 Image cached = cacheLib.getSourceCover(source);
156 if (cached != null) {
157 return cached;
158 }
159
160 return lib.getSourceCover(source);
161 }
162
163 @Override
164 public Image getAuthorCover(String author) throws IOException {
165 Image custom = getCustomAuthorCover(author);
166 if (custom != null) {
167 return custom;
168 }
169
170 Image cached = cacheLib.getAuthorCover(author);
171 if (cached != null) {
172 return cached;
173 }
174
175 return lib.getAuthorCover(author);
176 }
177
178 @Override
179 public Image getCustomSourceCover(String source) throws IOException {
180 Image custom = cacheLib.getCustomSourceCover(source);
181 if (custom == null) {
182 custom = lib.getCustomSourceCover(source);
183 if (custom != null) {
184 cacheLib.setSourceCover(source, custom);
185 }
186 }
187
188 return custom;
189 }
190
191 @Override
192 public Image getCustomAuthorCover(String author) throws IOException {
193 Image custom = cacheLib.getCustomAuthorCover(author);
194 if (custom == null) {
195 custom = lib.getCustomAuthorCover(author);
196 if (custom != null) {
197 cacheLib.setAuthorCover(author, custom);
198 }
199 }
200
201 return custom;
202 }
203
204 @Override
205 public void setSourceCover(String source, String luid) throws IOException {
206 lib.setSourceCover(source, luid);
207 cacheLib.setSourceCover(source, getCover(luid));
208 }
209
210 @Override
211 public void setAuthorCover(String author, String luid) throws IOException {
212 lib.setAuthorCover(author, luid);
213 cacheLib.setAuthorCover(author, getCover(luid));
214 }
215
216 @Override
217 protected void updateInfo(MetaData meta) throws IOException {
218 if (meta != null && metas != null) {
219 for (int i = 0; i < metas.size(); i++) {
220 if (metas.get(i).getLuid().equals(meta.getLuid())) {
221 metas.set(i, meta);
222 }
223 }
224 }
225
226 cacheLib.updateInfo(meta);
227 lib.updateInfo(meta);
228 }
229
230 @Override
231 protected void invalidateInfo(String luid) {
232 if (luid == null) {
233 metas = null;
234 } else if (metas != null) {
235 for (int i = 0; i < metas.size(); i++) {
236 if (metas.get(i).getLuid().equals(luid)) {
237 metas.remove(i--);
238 }
239 }
240 }
241
242 cacheLib.invalidateInfo(luid);
243 lib.invalidateInfo(luid);
244 }
245
246 @Override
247 public synchronized Story save(Story story, String luid, Progress pg)
248 throws IOException {
249 Progress pgLib = new Progress();
250 Progress pgCacheLib = new Progress();
251
252 if (pg == null) {
253 pg = new Progress();
254 }
255
256 pg.setMinMax(0, 2);
257 pg.addProgress(pgLib, 1);
258 pg.addProgress(pgCacheLib, 1);
259
260 story = lib.save(story, luid, pgLib);
261 story = cacheLib.save(story, story.getMeta().getLuid(), pgCacheLib);
262
263 updateInfo(story.getMeta());
264
265 return story;
266 }
267
268 @Override
269 public synchronized void delete(String luid) throws IOException {
270 if (isCached(luid)) {
271 cacheLib.delete(luid);
272 }
273 lib.delete(luid);
274
275 invalidateInfo(luid);
276 }
277
278 @Override
279 protected synchronized void changeSTA(String luid, String newSource,
280 String newTitle, String newAuthor, Progress pg) throws IOException {
281 if (pg == null) {
282 pg = new Progress();
283 }
284
285 Progress pgCache = new Progress();
286 Progress pgOrig = new Progress();
287 pg.setMinMax(0, 2);
288 pg.addProgress(pgCache, 1);
289 pg.addProgress(pgOrig, 1);
290
291 MetaData meta = getInfo(luid);
292 if (meta == null) {
293 throw new IOException("Story not found: " + luid);
294 }
295
296 if (isCached(luid)) {
297 cacheLib.changeSTA(luid, newSource, newTitle, newAuthor, pgCache);
298 }
299 pgCache.done();
300
301 lib.changeSTA(luid, newSource, newTitle, newAuthor, pgOrig);
302 pgOrig.done();
303
304 meta.setSource(newSource);
305 meta.setTitle(newTitle);
306 meta.setAuthor(newAuthor);
307 pg.done();
308
309 invalidateInfo(luid);
310 }
311
312 /**
313 * Check if the {@link Story} denoted by this Library UID is present in the
314 * cache.
315 *
316 * @param luid
317 * the Library UID
318 *
319 * @return TRUE if it is
320 */
321 public boolean isCached(String luid) {
322 try {
323 return cacheLib.getInfo(luid) != null;
324 } catch (IOException e) {
325 return false;
326 }
327 }
328
329 /**
330 * Clear the {@link Story} from the cache.
331 * <p>
332 * The next time we try to retrieve the {@link Story}, it may be required to
333 * cache it again.
334 *
335 * @param luid
336 * the story to clear
337 *
338 * @throws IOException
339 * in case of I/O error
340 */
341 public void clearFromCache(String luid) throws IOException {
342 if (isCached(luid)) {
343 cacheLib.delete(luid);
344 }
345 }
346
347 @Override
348 public Story imprt(URL url, Progress pg) throws IOException {
349 if (pg == null) {
350 pg = new Progress();
351 }
352
353 Progress pgImprt = new Progress();
354 Progress pgCache = new Progress();
355 pg.setMinMax(0, 10);
356 pg.addProgress(pgImprt, 7);
357 pg.addProgress(pgCache, 3);
358
359 Story story = lib.imprt(url, pgImprt);
360 cacheLib.save(story, story.getMeta().getLuid(), pgCache);
361
362 updateInfo(story.getMeta());
363
364 pg.done();
365 return story;
366 }
367
368 // All the following methods are only used by Save and Delete in
369 // BasicLibrary:
370
371 @Override
372 protected int getNextId() {
373 throw new java.lang.InternalError("Should not have been called");
374 }
375
376 @Override
377 protected void doDelete(String luid) throws IOException {
378 throw new java.lang.InternalError("Should not have been called");
379 }
380
381 @Override
382 protected Story doSave(Story story, Progress pg) throws IOException {
383 throw new java.lang.InternalError("Should not have been called");
384 }
385 }