X-Git-Url: http://git.nikiroo.be/?a=blobdiff_plain;f=src%2Fbe%2Fnikiroo%2Ffanfix%2Flibrary%2FBasicLibrary.java;h=8ec4e5620655ad148fb6b4b47b2c16d0f4284ee8;hb=97b36d32a43b7fbbd4938c95c4b40db0c68daa71;hp=f6daed620f86347a5ec84a44ee3e8e80b600eb09;hpb=5f42f329b6d1dd0d61f49dd9947fe487c39160ee;p=fanfix.git diff --git a/src/be/nikiroo/fanfix/library/BasicLibrary.java b/src/be/nikiroo/fanfix/library/BasicLibrary.java index f6daed6..8ec4e56 100644 --- a/src/be/nikiroo/fanfix/library/BasicLibrary.java +++ b/src/be/nikiroo/fanfix/library/BasicLibrary.java @@ -4,11 +4,11 @@ import java.io.File; import java.io.IOException; import java.net.URL; import java.net.UnknownHostException; -import java.util.AbstractMap.SimpleEntry; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.Map.Entry; +import java.util.Map; +import java.util.TreeMap; import be.nikiroo.fanfix.Instance; import be.nikiroo.fanfix.data.MetaData; @@ -158,8 +158,8 @@ abstract public class BasicLibrary { * Invalidate the {@link Story} cache (when the content should be re-read * because it was changed). */ - protected void deleteInfo() { - deleteInfo(null); + protected void invalidateInfo() { + invalidateInfo(null); } /** @@ -171,7 +171,7 @@ abstract public class BasicLibrary { * the LUID of the {@link Story} to clear from the cache, or NULL * for all stories */ - protected abstract void deleteInfo(String luid); + protected abstract void invalidateInfo(String luid); /** * Invalidate the {@link Story} cache (when the content has changed, but we @@ -246,6 +246,47 @@ abstract public class BasicLibrary { return list; } + /** + * List all the known types (sources) of stories, grouped by directory + * ("Source_1/a" and "Source_1/b" will be grouped into "Source_1"). + *

+ * Note that an empty item in the list means a non-grouped source (type) -- + * e.g., you could have for Source_1: + *

+ * + * @return the grouped list + */ + public synchronized Map> getSourcesGrouped() { + Map> map = new TreeMap>(); + for (String source : getSources()) { + String name; + String subname; + + int pos = source.indexOf('/'); + if (pos > 0 && pos < source.length() - 1) { + name = source.substring(0, pos); + subname = source.substring(pos + 1); + + } else { + name = source; + subname = ""; + } + + List list = map.get(name); + if (list == null) { + list = new ArrayList(); + map.put(name, list); + } + list.add(subname); + } + + return map; + } + /** * List all the known authors of stories. * @@ -283,48 +324,60 @@ abstract public class BasicLibrary { * * @return the authors' names, grouped by letter(s) */ - public List>> getAuthorsGrouped() { + public Map> getAuthorsGrouped() { int MAX = 20; - List>> groups = new ArrayList>>(); + Map> groups = new TreeMap>(); List authors = getAuthors(); + // If all authors fit the max, just report them as is if (authors.size() <= MAX) { - groups.add(new SimpleEntry>("", authors)); + groups.put("", authors); return groups; } - groups.add(new SimpleEntry>("*", getAuthorsGroup( - authors, '*'))); - groups.add(new SimpleEntry>("0-9", - getAuthorsGroup(authors, '0'))); - + // Create groups A to Z, which can be empty here for (char car = 'A'; car <= 'Z'; car++) { - groups.add(new SimpleEntry>(Character - .toString(car), getAuthorsGroup(authors, car))); + groups.put(Character.toString(car), getAuthorsGroup(authors, car)); } - // do NOT collapse * and [0-9] with the rest - for (int i = 2; i + 1 < groups.size(); i++) { - Entry> now = groups.get(i); - Entry> next = groups.get(i + 1); - int currentTotal = now.getValue().size() + next.getValue().size(); + // Collapse them + List keys = new ArrayList(groups.keySet()); + for (int i = 0; i + 1 < keys.size(); i++) { + String keyNow = keys.get(i); + String keyNext = keys.get(i + 1); + + List now = groups.get(keyNow); + List next = groups.get(keyNext); + + int currentTotal = now.size() + next.size(); if (currentTotal <= MAX) { - String key = now.getKey().charAt(0) + "-" - + next.getKey().charAt(next.getKey().length() - 1); + String key = keyNow.charAt(0) + "-" + + keyNext.charAt(keyNext.length() - 1); + List all = new ArrayList(); - all.addAll(now.getValue()); - all.addAll(next.getValue()); - groups.set(i, new SimpleEntry>(key, all)); - groups.remove(i + 1); - i--; + all.addAll(now); + all.addAll(next); + + groups.remove(keyNow); + groups.remove(keyNext); + groups.put(key, all); + + keys.set(i, key); // set the new key instead of key(i) + keys.remove(i + 1); // remove the next, consumed key + i--; // restart at key(i) } } - for (int i = 0; i < groups.size(); i++) { - if (groups.get(i).getValue().size() == 0) { - groups.remove(i); - i--; + // Add "special" groups + groups.put("*", getAuthorsGroup(authors, '*')); + groups.put("0-9", getAuthorsGroup(authors, '0')); + + // Prune empty groups + keys = new ArrayList(groups.keySet()); + for (String key : keys) { + if (groups.get(key).isEmpty()) { + groups.remove(key); } } @@ -375,7 +428,7 @@ abstract public class BasicLibrary { /** * List all the stories in the {@link BasicLibrary}. *

- * Cover images not included. + * Cover images MAYBE not included. * * @return the stories */ @@ -705,7 +758,7 @@ abstract public class BasicLibrary { this.getClass().getSimpleName() + ": deleting story " + luid); doDelete(luid); - deleteInfo(luid); + invalidateInfo(luid); Instance.getTraceHandler().trace( this.getClass().getSimpleName() + ": story deleted (" + luid @@ -732,7 +785,83 @@ abstract public class BasicLibrary { throw new IOException("Story not found: " + luid); } + changeSTA(luid, newSource, meta.getTitle(), meta.getAuthor(), pg); + } + + /** + * Change the title (name) of the given {@link Story}. + * + * @param luid + * the {@link Story} LUID + * @param newTitle + * the new title + * @param pg + * the optional progress reporter + * + * @throws IOException + * in case of I/O error or if the {@link Story} was not found + */ + public synchronized void changeTitle(String luid, String newTitle, + Progress pg) throws IOException { + MetaData meta = getInfo(luid); + if (meta == null) { + throw new IOException("Story not found: " + luid); + } + + changeSTA(luid, meta.getSource(), newTitle, meta.getAuthor(), pg); + } + + /** + * Change the author of the given {@link Story}. + * + * @param luid + * the {@link Story} LUID + * @param newAuthor + * the new author + * @param pg + * the optional progress reporter + * + * @throws IOException + * in case of I/O error or if the {@link Story} was not found + */ + public synchronized void changeAuthor(String luid, String newAuthor, + Progress pg) throws IOException { + MetaData meta = getInfo(luid); + if (meta == null) { + throw new IOException("Story not found: " + luid); + } + + changeSTA(luid, meta.getSource(), meta.getTitle(), newAuthor, pg); + } + + /** + * Change the Source, Title and Author of the {@link Story} in one single + * go. + * + * @param luid + * the {@link Story} LUID + * @param newSource + * the new source + * @param newTitle + * the new title + * @param newAuthor + * the new author + * @param pg + * the optional progress reporter + * + * @throws IOException + * in case of I/O error or if the {@link Story} was not found + */ + protected synchronized void changeSTA(String luid, String newSource, + String newTitle, String newAuthor, Progress pg) throws IOException { + MetaData meta = getInfo(luid); + if (meta == null) { + throw new IOException("Story not found: " + luid); + } + meta.setSource(newSource); + meta.setTitle(newTitle); + meta.setAuthor(newAuthor); saveMeta(meta, pg); } @@ -743,7 +872,7 @@ abstract public class BasicLibrary { * By default, delete the old {@link Story} then recreate a new * {@link Story}. *

- * Note that this behaviour can lead to data loss. + * Note that this behaviour can lead to data loss in case of problems! * * @param meta * the new {@link MetaData} (LUID MUST NOT change) @@ -769,8 +898,8 @@ abstract public class BasicLibrary { throw new IOException("Story not found: " + meta.getLuid()); } + // TODO: this is not safe! delete(meta.getLuid()); - story.setMeta(meta); save(story, meta.getLuid(), pgSet);