import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.Map;
import java.util.Map.Entry;
+import java.util.TreeMap;
import be.nikiroo.fanfix.Instance;
import be.nikiroo.fanfix.data.MetaData;
* 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);
}
/**
* 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
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").
+ * <p>
+ * Note that an empty item in the list means a non-grouped source (type) --
+ * e.g., you could have for Source_1:
+ * <ul>
+ * <li><tt></tt>: empty, so source is "Source_1"</li>
+ * <li><tt>a</tt>: empty, so source is "Source_1/a"</li>
+ * <li><tt>b</tt>: empty, so source is "Source_1/b"</li>
+ * </ul>
+ *
+ * @return the grouped list
+ */
+ public synchronized Map<String, List<String>> getSourcesGrouped() {
+ Map<String, List<String>> map = new TreeMap<String, List<String>>();
+ 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<String> list = map.get(name);
+ if (list == null) {
+ list = new ArrayList<String>();
+ map.put(name, list);
+ }
+ list.add(subname);
+ }
+
+ return map;
+ }
+
/**
* List all the known authors of stories.
*
/**
* List all the stories in the {@link BasicLibrary}.
* <p>
- * Cover images not included.
+ * Cover images <b>MAYBE</b> not included.
*
* @return the stories
*/
this.getClass().getSimpleName() + ": deleting story " + luid);
doDelete(luid);
- deleteInfo(luid);
+ invalidateInfo(luid);
Instance.getTraceHandler().trace(
this.getClass().getSimpleName() + ": story deleted (" + luid
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);
}
* By default, delete the old {@link Story} then recreate a new
* {@link Story}.
* <p>
- * 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 <b>MUST NOT</b> change)
throw new IOException("Story not found: " + meta.getLuid());
}
+ // TODO: this is not safe!
delete(meta.getLuid());
-
story.setMeta(meta);
save(story, meta.getLuid(), pgSet);