import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
+import be.nikiroo.fanfix.bundles.Config;
import be.nikiroo.fanfix.data.MetaData;
import be.nikiroo.fanfix.data.Story;
import be.nikiroo.fanfix.output.BasicOutput;
import be.nikiroo.fanfix.supported.BasicSupport;
import be.nikiroo.fanfix.supported.BasicSupport.SupportType;
import be.nikiroo.fanfix.supported.InfoReader;
+import be.nikiroo.utils.IOUtils;
+import be.nikiroo.utils.Progress;
/**
* Manage a library of Stories: import, export, list.
*
* @return the types
*/
- public List<String> getTypes() {
+ public synchronized List<String> getTypes() {
List<String> list = new ArrayList<String>();
for (Entry<MetaData, File> entry : getStories().entrySet()) {
- String storyType = entry.getValue().getParentFile().getName();
+ String storyType = entry.getKey().getSource();
if (!list.contains(storyType)) {
list.add(storyType);
}
}
+ Collections.sort(list);
+ return list;
+ }
+
+ /**
+ * List all the known authors of stories.
+ *
+ * @return the authors
+ */
+ public synchronized List<String> getAuthors() {
+ List<String> list = new ArrayList<String>();
+ for (Entry<MetaData, File> entry : getStories().entrySet()) {
+ String storyAuthor = entry.getKey().getAuthor();
+ if (!list.contains(storyAuthor)) {
+ list.add(storyAuthor);
+ }
+ }
+
+ Collections.sort(list);
+ return list;
+ }
+
+ /**
+ * List all the stories of the given author in the {@link Library}, or all
+ * the stories if NULL is passed as an author.
+ *
+ * @param author
+ * the author of the stories to retrieve, or NULL for all
+ *
+ * @return the stories
+ */
+ public synchronized List<MetaData> getListByAuthor(String author) {
+ List<MetaData> list = new ArrayList<MetaData>();
+ for (Entry<MetaData, File> entry : getStories().entrySet()) {
+ String storyAuthor = entry.getKey().getAuthor();
+ if (author == null || author.equalsIgnoreCase(storyAuthor)) {
+ list.add(entry.getKey());
+ }
+ }
+
+ Collections.sort(list);
return list;
}
*
* @return the stories
*/
- public List<MetaData> getList(String type) {
+ public synchronized List<MetaData> getListByType(String type) {
List<MetaData> list = new ArrayList<MetaData>();
for (Entry<MetaData, File> entry : getStories().entrySet()) {
String storyType = entry.getValue().getParentFile().getName();
}
}
+ Collections.sort(list);
return list;
}
*
* @return the corresponding {@link Story}
*/
- public MetaData getInfo(String luid) {
+ public synchronized MetaData getInfo(String luid) {
if (luid != null) {
for (Entry<MetaData, File> entry : getStories().entrySet()) {
if (luid.equals(entry.getKey().getLuid())) {
*
* @return the corresponding {@link Story}
*/
- public File getFile(String luid) {
+ public synchronized File getFile(String luid) {
if (luid != null) {
for (Entry<MetaData, File> entry : getStories().entrySet()) {
if (luid.equals(entry.getKey().getLuid())) {
*
* @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
*/
- public Story getStory(String luid) {
+ public synchronized Story getStory(String luid, Progress pg) {
if (luid != null) {
for (Entry<MetaData, File> entry : getStories().entrySet()) {
if (luid.equals(entry.getKey().getLuid())) {
.getKey().getType());
URL url = entry.getValue().toURI().toURL();
if (type != null) {
- return BasicSupport.getSupport(type).process(url);
+ return BasicSupport.getSupport(type).process(url,
+ pg);
} else {
throw new IOException("Unknown type: "
+ entry.getKey().getType());
}
}
+ if (pg != null) {
+ pg.setMinMax(0, 1);
+ pg.setProgress(1);
+ }
+
return null;
}
*
* @param url
* the {@link URL} to import
+ * @param pg
+ * the optional progress reporter
*
* @return the imported {@link Story}
*
* @throws IOException
* in case of I/O error
*/
- public Story imprt(URL url) throws IOException {
+ public Story imprt(URL url, Progress pg) throws IOException {
BasicSupport support = BasicSupport.getSupport(url);
if (support == null) {
throw new IOException("URL not supported: " + url.toString());
}
- return save(support.process(url), null);
+ return save(support.process(url, pg), null);
}
/**
* the {@link OutputType} to transform it to
* @param target
* the target to save to
+ * @param pg
+ * the optional progress reporter
*
* @return the saved resource (the main saved {@link File})
*
* @throws IOException
* in case of I/O error
*/
- public File export(String luid, OutputType type, String target)
+ public File export(String luid, OutputType type, String target, Progress pg)
throws IOException {
+ Progress pgGetStory = new Progress();
+ Progress pgOut = new Progress();
+ if (pg != null) {
+ pg.setMax(2);
+ pg.addProgress(pgGetStory, 1);
+ pg.addProgress(pgOut, 1);
+ }
+
BasicOutput out = BasicOutput.getOutput(type, true);
if (out == null) {
throw new IOException("Output type not supported: " + type);
}
- Story story = getStory(luid);
+ Story story = getStory(luid, pgGetStory);
if (story == null) {
throw new IOException("Cannot find story to export: " + luid);
}
- return out.process(getStory(luid), target);
+ return out.process(story, target, pgOut);
}
/**
*
* @param story
* the {@link Story} to save
+ * @param pg
+ * the optional progress reporter
*
* @return the same {@link Story}, whose LUID may have changed
*
* @throws IOException
* in case of I/O error
*/
- public Story save(Story story) throws IOException {
- return save(story, null);
+ public Story save(Story story, Progress pg) throws IOException {
+ return save(story, null, pg);
}
/**
* the {@link Story} to save
* @param luid
* the <b>correct</b> LUID or NULL to get the next free one
+ * @param pg
+ * the optional progress reporter
*
* @return the same {@link Story}, whose LUID may have changed
*
* @throws IOException
* in case of I/O error
*/
- private Story save(Story story, String luid) throws IOException {
+ public synchronized Story save(Story story, String luid, Progress pg)
+ throws IOException {
// Do not change the original metadata, but change the original story
MetaData key = story.getMeta().clone();
story.setMeta(key);
}
BasicOutput it = BasicOutput.getOutput(out, true);
- File file = it.process(story, getFile(key).getPath());
- getStories().put(story.getMeta(), file);
+ it.process(story, getFile(key).getPath(), pg);
+
+ // empty cache
+ stories.clear();
return story;
}
+ /**
+ * Delete the given {@link Story} from this {@link Library}.
+ *
+ * @param luid
+ * the LUID of the target {@link Story}
+ *
+ * @return TRUE if it was deleted
+ */
+ public synchronized boolean delete(String luid) {
+ boolean ok = false;
+
+ MetaData meta = getInfo(luid);
+ File file = getStories().get(meta);
+
+ if (file != null) {
+ if (file.delete()) {
+ String readerExt = getOutputType(meta)
+ .getDefaultExtension(true);
+ String fileExt = getOutputType(meta).getDefaultExtension(false);
+
+ String path = file.getAbsolutePath();
+ if (readerExt != null && !readerExt.equals(fileExt)) {
+ path = path
+ .substring(0, path.length() - readerExt.length())
+ + fileExt;
+ file = new File(path);
+ IOUtils.deltree(file);
+ }
+
+ File infoFile = new File(path + ".info");
+ if (!infoFile.exists()) {
+ infoFile = new File(path.substring(0, path.length()
+ - fileExt.length())
+ + ".info");
+ }
+ infoFile.delete();
+
+ String coverExt = "."
+ + Instance.getConfig().getString(
+ Config.IMAGE_FORMAT_COVER);
+ File coverFile = new File(path + coverExt);
+ if (!coverFile.exists()) {
+ coverFile = new File(path.substring(0, path.length()
+ - fileExt.length()));
+ }
+ coverFile.delete();
+
+ ok = true;
+ }
+
+ // clear cache
+ stories.clear();
+ }
+
+ return ok;
+ }
+
/**
* The directory (full path) where the {@link Story} related to this
* {@link MetaData} should be located on disk.
* @return the target
*/
private File getFile(MetaData key) {
- String title = key.getTitle().replaceAll("[^a-zA-Z0-9._+-]", "_");
+ String title = key.getTitle();
+ if (title == null) {
+ title = "";
+ }
+ title = title.replaceAll("[^a-zA-Z0-9._+-]", "_");
return new File(getDir(key), key.getLuid() + "_" + title);
}
*
* @return the stories
*/
- private Map<MetaData, File> getStories() {
+ private synchronized Map<MetaData, File> getStories() {
if (stories.isEmpty()) {
lastId = 0;
- ext.length());
String newExt = getOutputType(meta)
- .getDefaultExtension();
+ .getDefaultExtension(true);
file = new File(path + newExt);
//