X-Git-Url: http://git.nikiroo.be/?a=blobdiff_plain;f=src%2Fbe%2Fnikiroo%2Ffanfix%2Flibrary%2FBasicLibrary.java;h=586c4ef17e11ff4d8c7eefa1cf6c689dac71ce59;hb=67b8ce74c4277c894aba234a7a493a93f6225a69;hp=8ec4e5620655ad148fb6b4b47b2c16d0f4284ee8;hpb=97b36d32a43b7fbbd4938c95c4b40db0c68daa71;p=nikiroo-utils.git diff --git a/src/be/nikiroo/fanfix/library/BasicLibrary.java b/src/be/nikiroo/fanfix/library/BasicLibrary.java index 8ec4e56..586c4ef 100644 --- a/src/be/nikiroo/fanfix/library/BasicLibrary.java +++ b/src/be/nikiroo/fanfix/library/BasicLibrary.java @@ -39,14 +39,36 @@ abstract public class BasicLibrary { * @author niki */ public enum Status { - /** The library is ready. */ - READY, + /** The library is ready and r/w. */ + READ_WRITE, + /** The library is ready, but read-only. */ + READ_ONLY, /** The library is invalid (not correctly set up). */ INVALID, /** You are not allowed to access this library. */ - UNAUTORIZED, + UNAUTHORIZED, /** The library is currently out of commission. */ - UNAVAILABLE, + UNAVAILABLE; + + /** + * The library is available (you can query it). + *

+ * It does not specify if it is read-only or not. + * + * @return TRUE if it is + */ + public boolean isReady() { + return (this == READ_WRITE || this == READ_ONLY); + } + + /** + * This library can be modified (= you are allowed to modify it). + * + * @return TRUE if it is + */ + public boolean isWritable() { + return (this == READ_WRITE); + } } /** @@ -66,7 +88,7 @@ abstract public class BasicLibrary { * @return the current status */ public Status getStatus() { - return Status.READY; + return Status.READ_WRITE; } /** @@ -76,13 +98,16 @@ abstract public class BasicLibrary { * Do NOT alter this file. * * @param luid - * the Library UID of the story + * the Library UID of the story, can be NULL * @param pg * the optional {@link Progress} * * @return the corresponding {@link Story} + * + * @throws IOException + * in case of IOException */ - public abstract File getFile(String luid, Progress pg); + public abstract File getFile(String luid, Progress pg) throws IOException; /** * Return the cover image associated to this story. @@ -91,8 +116,18 @@ abstract public class BasicLibrary { * the Library UID of the story * * @return the cover image + * + * @throws IOException + * in case of IOException */ - public abstract Image getCover(String luid); + public abstract Image getCover(String luid) throws IOException; + + // TODO: ensure it is the main used interface + public MetaResultList getList(Progress pg) throws IOException { + return new MetaResultList(getMetas(pg)); + } + + // TODO: make something for (normal and custom) not-story covers /** * Return the cover image associated to this source. @@ -104,14 +139,45 @@ abstract public class BasicLibrary { * the source * * @return the cover image or NULL + * + * @throws IOException + * in case of IOException */ - public Image getSourceCover(String source) { + public Image getSourceCover(String source) throws IOException { Image custom = getCustomSourceCover(source); if (custom != null) { return custom; } - List metas = getListBySource(source); + List metas = getList().filter(source, null, null); + if (metas.size() > 0) { + return getCover(metas.get(0).getLuid()); + } + + return null; + } + + /** + * Return the cover image associated to this author. + *

+ * By default, return the custom cover if any, and if not, return the cover + * of the first story with this author. + * + * @param author + * the author + * + * @return the cover image or NULL + * + * @throws IOException + * in case of IOException + */ + public Image getAuthorCover(String author) throws IOException { + Image custom = getCustomAuthorCover(author); + if (custom != null) { + return custom; + } + + List metas = getList().filter(null, author, null); if (metas.size() > 0) { return getCover(metas.get(0).getLuid()); } @@ -128,31 +194,76 @@ abstract public class BasicLibrary { * the source to look for * * @return the custom cover or NULL if none + * + * @throws IOException + * in case of IOException + */ + @SuppressWarnings("unused") + public Image getCustomSourceCover(String source) throws IOException { + return null; + } + + /** + * Return the custom cover image associated to this author. + *

+ * By default, return NULL. + * + * @param author + * the author to look for + * + * @return the custom cover or NULL if none + * + * @throws IOException + * in case of IOException */ - public Image getCustomSourceCover(@SuppressWarnings("unused") String source) { + @SuppressWarnings("unused") + public Image getCustomAuthorCover(String author) throws IOException { return null; } /** - * Fix the source cover to the given story cover. + * Set the source cover to the given story cover. * * @param source * the source to change * @param luid * the story LUID + * + * @throws IOException + * in case of IOException + */ + public abstract void setSourceCover(String source, String luid) + throws IOException; + + /** + * Set the author cover to the given story cover. + * + * @param author + * the author to change + * @param luid + * the story LUID + * + * @throws IOException + * in case of IOException */ - public abstract void setSourceCover(String source, String luid); + public abstract void setAuthorCover(String author, String luid) + throws IOException; /** * Return the list of stories (represented by their {@link MetaData}, which * MAY not have the cover included). + *

+ * The returned list MUST be a copy, not the original one. * * @param pg * the optional {@link Progress} * * @return the list (can be empty but not NULL) + * + * @throws IOException + * in case of IOException */ - protected abstract List getMetas(Progress pg); + protected abstract List getMetas(Progress pg) throws IOException; /** * Invalidate the {@link Story} cache (when the content should be re-read @@ -179,8 +290,11 @@ abstract public class BasicLibrary { * * @param meta * the {@link Story} to clear from the cache + * + * @throws IOException + * in case of IOException */ - protected abstract void updateInfo(MetaData meta); + protected abstract void updateInfo(MetaData meta) throws IOException; /** * Return the next LUID that can be used. @@ -225,15 +339,52 @@ abstract public class BasicLibrary { * the optional progress reporter */ public void refresh(Progress pg) { - getMetas(pg); + try { + getMetas(pg); + } catch (IOException e) { + // We will let it fail later + } + } + + /** + * Check if the {@link Story} denoted by this Library UID is present in the + * cache (if we have no cache, we default to true). + * + * @param luid + * the Library UID + * + * @return TRUE if it is + */ + public boolean isCached(String luid) { + // By default, everything is cached + return true; + } + + /** + * Clear the {@link Story} from the cache, if needed. + *

+ * The next time we try to retrieve the {@link Story}, it may be required to + * cache it again. + * + * @param luid + * the story to clear + * + * @throws IOException + * in case of I/O error + */ + public void clearFromCache(String luid) throws IOException { + // By default, this is a noop. } /** * List all the known types (sources) of stories. * * @return the sources + * + * @throws IOException + * in case of IOException */ - public synchronized List getSources() { + public List getSources() throws IOException { List list = new ArrayList(); for (MetaData meta : getMetas(null)) { String storySource = meta.getSource(); @@ -259,8 +410,11 @@ abstract public class BasicLibrary { * * * @return the grouped list + * + * @throws IOException + * in case of IOException */ - public synchronized Map> getSourcesGrouped() { + public Map> getSourcesGrouped() throws IOException { Map> map = new TreeMap>(); for (String source : getSources()) { String name; @@ -291,8 +445,11 @@ abstract public class BasicLibrary { * List all the known authors of stories. * * @return the authors + * + * @throws IOException + * in case of IOException */ - public synchronized List getAuthors() { + public List getAuthors() throws IOException { List list = new ArrayList(); for (MetaData meta : getMetas(null)) { String storyAuthor = meta.getAuthor(); @@ -323,8 +480,11 @@ abstract public class BasicLibrary { * 0-9, which may only be present or not). * * @return the authors' names, grouped by letter(s) + * + * @throws IOException + * in case of IOException */ - public Map> getAuthorsGrouped() { + public Map> getAuthorsGrouped() throws IOException { int MAX = 20; Map> groups = new TreeMap>(); @@ -399,7 +559,8 @@ abstract public class BasicLibrary { * @param car * the starting character, *, 0 or a capital * letter - * @return the authors that fulfill the starting letter + * + * @return the authors that fulfil the starting letter */ private List getAuthorsGroup(List authors, char car) { List accepted = new ArrayList(); @@ -431,91 +592,95 @@ abstract public class BasicLibrary { * Cover images MAYBE not included. * * @return the stories - */ - public synchronized List getList() { - return getMetas(null); - } - - /** - * List all the stories of the given source type in the {@link BasicLibrary} - * , or all the stories if NULL is passed as a type. - *

- * Cover images not included. * - * @param type - * the type of story to retrieve, or NULL for all - * - * @return the stories + * @throws IOException + * in case of IOException */ - public synchronized List getListBySource(String type) { - List list = new ArrayList(); - for (MetaData meta : getMetas(null)) { - String storyType = meta.getSource(); - if (type == null || type.equalsIgnoreCase(storyType)) { - list.add(meta); - } - } - - Collections.sort(list); - return list; + public MetaResultList getList() throws IOException { + return getList(null); } /** - * List all the stories of the given author in the {@link BasicLibrary}, or - * all the stories if NULL is passed as an author. - *

- * Cover images not included. + * Retrieve a {@link MetaData} corresponding to the given {@link Story}, + * cover image MAY not be included. * - * @param author - * the author of the stories to retrieve, or NULL for all + * @param luid + * the Library UID of the story, can be NULL * - * @return the stories + * @return the corresponding {@link Story} or NULL if not found + * + * @throws IOException + * in case of IOException */ - public synchronized List getListByAuthor(String author) { - List list = new ArrayList(); - for (MetaData meta : getMetas(null)) { - String storyAuthor = meta.getAuthor(); - if (author == null || author.equalsIgnoreCase(storyAuthor)) { - list.add(meta); + public MetaData getInfo(String luid) throws IOException { + if (luid != null) { + for (MetaData meta : getMetas(null)) { + if (luid.equals(meta.getLuid())) { + return meta; + } } } - Collections.sort(list); - return list; + return null; } /** - * Retrieve a {@link MetaData} corresponding to the given {@link Story}, - * cover image MAY not be included. + * Retrieve a specific {@link Story}. * * @param luid * the Library UID of the story + * @param pg + * the optional progress reporter * - * @return the corresponding {@link Story} + * @return the corresponding {@link Story} or NULL if not found + * + * @throws IOException + * in case of IOException */ - public synchronized MetaData getInfo(String luid) { - if (luid != null) { - for (MetaData meta : getMetas(null)) { - if (luid.equals(meta.getLuid())) { - return meta; - } + public synchronized Story getStory(String luid, Progress pg) + throws IOException { + Progress pgMetas = new Progress(); + Progress pgStory = new Progress(); + if (pg != null) { + pg.setMinMax(0, 100); + pg.addProgress(pgMetas, 10); + pg.addProgress(pgStory, 90); + } + + MetaData meta = null; + for (MetaData oneMeta : getMetas(pgMetas)) { + if (oneMeta.getLuid().equals(luid)) { + meta = oneMeta; + break; } } - return null; + pgMetas.done(); + + Story story = getStory(luid, meta, pgStory); + pgStory.done(); + + return story; } /** * Retrieve a specific {@link Story}. * * @param luid - * the Library UID of the story + * the LUID of the story + * @param meta + * the meta of the story * @param pg * the optional progress reporter * * @return the corresponding {@link Story} or NULL if not found + * + * @throws IOException + * in case of IOException */ - public synchronized Story getStory(String luid, Progress pg) { + public synchronized Story getStory(String luid, MetaData meta, Progress pg) + throws IOException { + if (pg == null) { pg = new Progress(); } @@ -528,39 +693,38 @@ abstract public class BasicLibrary { pg.addProgress(pgProcess, 1); Story story = null; - for (MetaData meta : getMetas(null)) { - if (meta.getLuid().equals(luid)) { - File file = getFile(luid, pgGet); - pgGet.done(); - try { - SupportType type = SupportType.valueOfAllOkUC(meta - .getType()); - URL url = file.toURI().toURL(); - if (type != null) { - story = BasicSupport.getSupport(type, url) // - .process(pgProcess); - - // Because we do not want to clear the meta cache: - meta.setCover(story.getMeta().getCover()); - meta.setResume(story.getMeta().getResume()); - story.setMeta(meta); - // - } else { - throw new IOException("Unknown type: " + meta.getType()); - } - } catch (IOException e) { - // We should not have not-supported files in the - // library - Instance.getTraceHandler().error( - new IOException("Cannot load file from library: " - + file, e)); - } finally { - pgProcess.done(); - pg.done(); + File file = null; + + if (luid != null && meta != null) { + file = getFile(luid, pgGet); + } + + pgGet.done(); + try { + if (file != null) { + SupportType type = SupportType.valueOfAllOkUC(meta.getType()); + if (type == null) { + throw new IOException("Unknown type: " + meta.getType()); } - break; + URL url = file.toURI().toURL(); + story = BasicSupport.getSupport(type, url) // + .process(pgProcess); + + // Because we do not want to clear the meta cache: + meta.setCover(story.getMeta().getCover()); + meta.setResume(story.getMeta().getResume()); + story.setMeta(meta); } + } catch (IOException e) { + // We should not have not-supported files in the library + Instance.getInstance().getTraceHandler() + .error(new IOException(String.format( + "Cannot load file of type '%s' from library: %s", + meta.getType(), file), e)); + } finally { + pgProcess.done(); + pg.done(); } return story; @@ -575,14 +739,14 @@ abstract public class BasicLibrary { * @param pg * the optional progress reporter * - * @return the imported {@link Story} + * @return the imported Story {@link MetaData} * * @throws UnknownHostException * if the host is not supported * @throws IOException * in case of I/O error */ - public Story imprt(URL url, Progress pg) throws IOException { + public MetaData imprt(URL url, Progress pg) throws IOException { if (pg == null) pg = new Progress(); @@ -598,9 +762,10 @@ abstract public class BasicLibrary { } Story story = save(support.process(pgProcess), pgSave); + pg.setName(story.getMeta().getTitle()); pg.done(); - return story; + return story.getMeta(); } /** @@ -715,14 +880,19 @@ abstract public class BasicLibrary { */ public synchronized Story save(Story story, String luid, Progress pg) throws IOException { + if (pg == null) { + pg = new Progress(); + } - Instance.getTraceHandler().trace( + Instance.getInstance().getTraceHandler().trace( this.getClass().getSimpleName() + ": saving story " + luid); // Do not change the original metadata, but change the original story MetaData meta = story.getMeta().clone(); story.setMeta(meta); + pg.setName("Saving story"); + if (luid == null || luid.isEmpty()) { meta.setLuid(String.format("%03d", getNextId())); } else { @@ -737,10 +907,12 @@ abstract public class BasicLibrary { updateInfo(story.getMeta()); - Instance.getTraceHandler().trace( - this.getClass().getSimpleName() + ": story saved (" + luid - + ")"); + Instance.getInstance().getTraceHandler() + .trace(this.getClass().getSimpleName() + ": story saved (" + + luid + ")"); + pg.setName(meta.getTitle()); + pg.done(); return story; } @@ -754,15 +926,15 @@ abstract public class BasicLibrary { * in case of I/O error */ public synchronized void delete(String luid) throws IOException { - Instance.getTraceHandler().trace( + Instance.getInstance().getTraceHandler().trace( this.getClass().getSimpleName() + ": deleting story " + luid); doDelete(luid); invalidateInfo(luid); - Instance.getTraceHandler().trace( - this.getClass().getSimpleName() + ": story deleted (" + luid - + ")"); + Instance.getInstance().getTraceHandler() + .trace(this.getClass().getSimpleName() + ": story deleted (" + + luid + ")"); } /**