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