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