9432b33f5a0fb0b46fa360e3ca882fe3386bb87e
[fanfix.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) {
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 File getFile(final String luid, Progress pg) {
70 if (pg == null) {
71 pg = new Progress();
72 }
73
74 Progress pgImport = new Progress();
75 Progress pgGet = new Progress();
76 Progress pgRecall = new Progress();
77
78 pg.setMinMax(0, 5);
79 pg.addProgress(pgImport, 3);
80 pg.addProgress(pgGet, 1);
81 pg.addProgress(pgRecall, 1);
82
83 if (!isCached(luid)) {
84 try {
85 cacheLib.imprt(lib, luid, pgImport);
86 updateInfo(cacheLib.getInfo(luid));
87 pgImport.done();
88 } catch (IOException e) {
89 Instance.getTraceHandler().error(e);
90 }
91
92 pgImport.done();
93 pgGet.done();
94 }
95
96 File file = cacheLib.getFile(luid, pgRecall);
97 pgRecall.done();
98
99 pg.done();
100 return file;
101 }
102
103 @Override
104 public Image getCover(final String luid) {
105 if (isCached(luid)) {
106 return cacheLib.getCover(luid);
107 }
108
109 // We could update the cache here, but it's not easy
110 return lib.getCover(luid);
111 }
112
113 @Override
114 public Image getSourceCover(String source) {
115 Image custom = getCustomSourceCover(source);
116 if (custom != null) {
117 return custom;
118 }
119
120 Image cached = cacheLib.getSourceCover(source);
121 if (cached != null) {
122 return cached;
123 }
124
125 return lib.getSourceCover(source);
126 }
127
128 @Override
129 public Image getAuthorCover(String author) {
130 Image custom = getCustomAuthorCover(author);
131 if (custom != null) {
132 return custom;
133 }
134
135 Image cached = cacheLib.getAuthorCover(author);
136 if (cached != null) {
137 return cached;
138 }
139
140 return lib.getAuthorCover(author);
141 }
142
143 @Override
144 public Image getCustomSourceCover(String source) {
145 Image custom = cacheLib.getCustomSourceCover(source);
146 if (custom == null) {
147 custom = lib.getCustomSourceCover(source);
148 if (custom != null) {
149 cacheLib.setSourceCover(source, custom);
150 }
151 }
152
153 return custom;
154 }
155
156 @Override
157 public Image getCustomAuthorCover(String author) {
158 Image custom = cacheLib.getCustomAuthorCover(author);
159 if (custom == null) {
160 custom = lib.getCustomAuthorCover(author);
161 if (custom != null) {
162 cacheLib.setAuthorCover(author, custom);
163 }
164 }
165
166 return custom;
167 }
168
169 @Override
170 public void setSourceCover(String source, String luid) {
171 lib.setSourceCover(source, luid);
172 cacheLib.setSourceCover(source, getCover(luid));
173 }
174
175 @Override
176 public void setAuthorCover(String author, String luid) {
177 lib.setAuthorCover(author, luid);
178 cacheLib.setAuthorCover(author, getCover(luid));
179 }
180
181 @Override
182 protected void updateInfo(MetaData meta) {
183 if (meta != null && metas != null) {
184 for (int i = 0; i < metas.size(); i++) {
185 if (metas.get(i).getLuid().equals(meta.getLuid())) {
186 metas.set(i, meta);
187 }
188 }
189 }
190
191 cacheLib.updateInfo(meta);
192 lib.updateInfo(meta);
193 }
194
195 @Override
196 protected void invalidateInfo(String luid) {
197 if (luid == null) {
198 metas = null;
199 } else if (metas != null) {
200 for (int i = 0; i < metas.size(); i++) {
201 if (metas.get(i).getLuid().equals(luid)) {
202 metas.remove(i--);
203 }
204 }
205 }
206
207 cacheLib.invalidateInfo(luid);
208 lib.invalidateInfo(luid);
209 }
210
211 @Override
212 public synchronized Story save(Story story, String luid, Progress pg)
213 throws IOException {
214 Progress pgLib = new Progress();
215 Progress pgCacheLib = new Progress();
216
217 if (pg == null) {
218 pg = new Progress();
219 }
220
221 pg.setMinMax(0, 2);
222 pg.addProgress(pgLib, 1);
223 pg.addProgress(pgCacheLib, 1);
224
225 story = lib.save(story, luid, pgLib);
226 story = cacheLib.save(story, story.getMeta().getLuid(), pgCacheLib);
227
228 updateInfo(story.getMeta());
229
230 return story;
231 }
232
233 @Override
234 public synchronized void delete(String luid) throws IOException {
235 if (isCached(luid)) {
236 cacheLib.delete(luid);
237 }
238 lib.delete(luid);
239
240 MetaData meta = getInfo(luid);
241 if (meta != null) {
242 metas.remove(meta);
243 }
244 }
245
246 @Override
247 protected synchronized void changeSTA(String luid, String newSource,
248 String newTitle, String newAuthor, Progress pg) throws IOException {
249 if (pg == null) {
250 pg = new Progress();
251 }
252
253 Progress pgCache = new Progress();
254 Progress pgOrig = new Progress();
255 pg.setMinMax(0, 2);
256 pg.addProgress(pgCache, 1);
257 pg.addProgress(pgOrig, 1);
258
259 MetaData meta = getInfo(luid);
260 if (meta == null) {
261 throw new IOException("Story not found: " + luid);
262 }
263
264 if (isCached(luid)) {
265 cacheLib.changeSTA(luid, newSource, newTitle, newAuthor, pgCache);
266 }
267 pgCache.done();
268
269 lib.changeSTA(luid, newSource, newTitle, newAuthor, pgOrig);
270 pgOrig.done();
271
272 meta.setSource(newSource);
273 meta.setTitle(newTitle);
274 meta.setAuthor(newAuthor);
275 pg.done();
276 }
277
278 /**
279 * Check if the {@link Story} denoted by this Library UID is present in the
280 * cache.
281 *
282 * @param luid
283 * the Library UID
284 *
285 * @return TRUE if it is
286 */
287 public boolean isCached(String luid) {
288 return cacheLib.getInfo(luid) != null;
289 }
290
291 /**
292 * Clear the {@link Story} from the cache.
293 * <p>
294 * The next time we try to retrieve the {@link Story}, it may be required to
295 * cache it again.
296 *
297 * @param luid
298 * the story to clear
299 *
300 * @throws IOException
301 * in case of I/O error
302 */
303 public void clearFromCache(String luid) throws IOException {
304 if (isCached(luid)) {
305 cacheLib.delete(luid);
306 }
307 }
308
309 @Override
310 public Story imprt(URL url, Progress pg) throws IOException {
311 if (pg == null) {
312 pg = new Progress();
313 }
314
315 Progress pgImprt = new Progress();
316 Progress pgCache = new Progress();
317 pg.setMinMax(0, 10);
318 pg.addProgress(pgImprt, 7);
319 pg.addProgress(pgCache, 3);
320
321 Story story = lib.imprt(url, pgImprt);
322 cacheLib.save(story, story.getMeta().getLuid(), pgCache);
323
324 updateInfo(story.getMeta());
325
326 pg.done();
327 return story;
328 }
329
330 // All the following methods are only used by Save and Delete in
331 // BasicLibrary:
332
333 @Override
334 protected int getNextId() {
335 throw new java.lang.InternalError("Should not have been called");
336 }
337
338 @Override
339 protected void doDelete(String luid) throws IOException {
340 throw new java.lang.InternalError("Should not have been called");
341 }
342
343 @Override
344 protected Story doSave(Story story, Progress pg) throws IOException {
345 throw new java.lang.InternalError("Should not have been called");
346 }
347 }