import java.io.IOException;
import java.net.URL;
import java.net.UnknownHostException;
-import java.util.ArrayList;
-import java.util.Collections;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
-import java.util.TreeMap;
import be.nikiroo.fanfix.Instance;
import be.nikiroo.fanfix.data.MetaData;
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. */
UNAUTHORIZED,
- /** The library is currently out of commission. */
+ /** The library is invalid, and will never work as is. */
+ INVALID,
+ /** The library is currently out of commission, but may work later. */
UNAVAILABLE;
/**
*/
public abstract Image getCover(String luid) throws IOException;
- // TODO: ensure it is the main used interface
+ /**
+ * Retrieve the list of {@link MetaData} known by this {@link BasicLibrary}
+ * in a easy-to-filter version.
+ *
+ * @param pg
+ * the optional {@link Progress}
+ * @return the list of {@link MetaData} as a {@link MetaResultList} you can
+ * query
+ * @throws IOException
+ * in case of I/O eror
+ */
public MetaResultList getList(Progress pg) throws IOException {
+ // TODO: ensure it is the main used interface
+
return new MetaResultList(getMetas(pg));
}
- // TODO: make something for (normal and custom) not-story covers
+ // TODO: make something for (normal and custom) non-story covers
/**
* Return the cover image associated to this source.
*
* @return the next luid
*/
- protected abstract int getNextId();
+ protected abstract String getNextId();
/**
* Delete the target {@link Story}.
/**
* Check if the {@link Story} denoted by this Library UID is present in the
- * cache (if we have no cache, we default to </t>true</tt>).
+ * cache (if we have no cache, we default to </tt>true</tt>).
*
* @param luid
* the Library UID
*
* @return TRUE if it is
*/
- public boolean isCached(String luid) {
+ public boolean isCached(@SuppressWarnings("unused") String luid) {
// By default, everything is cached
return true;
}
* @throws IOException
* in case of I/O error
*/
+ @SuppressWarnings("unused")
public void clearFromCache(String luid) throws IOException {
// By default, this is a noop.
}
/**
- * List all the known types (sources) of stories.
- *
- * @return the sources
- *
+ * @return the same as getList()
* @throws IOException
- * in case of IOException
+ * in case of I/O error
+ * @deprecated please use {@link BasicLibrary#getList()} and
+ * {@link MetaResultList#getSources()} instead.
*/
+ @Deprecated
public List<String> getSources() throws IOException {
- List<String> list = new ArrayList<String>();
- for (MetaData meta : getMetas(null)) {
- String storySource = meta.getSource();
- if (!list.contains(storySource)) {
- list.add(storySource);
- }
- }
-
- Collections.sort(list);
- return list;
+ return getList().getSources();
}
/**
- * 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
- *
+ * @return the same as getList()
* @throws IOException
- * in case of IOException
+ * in case of I/O error
+ * @deprecated please use {@link BasicLibrary#getList()} and
+ * {@link MetaResultList#getSourcesGrouped()} instead.
*/
+ @Deprecated
public Map<String, List<String>> getSourcesGrouped() throws IOException {
- 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;
+ return getList().getSourcesGrouped();
}
/**
- * List all the known authors of stories.
- *
- * @return the authors
- *
+ * @return the same as getList()
* @throws IOException
- * in case of IOException
+ * in case of I/O error
+ * @deprecated please use {@link BasicLibrary#getList()} and
+ * {@link MetaResultList#getAuthors()} instead.
*/
+ @Deprecated
public List<String> getAuthors() throws IOException {
- List<String> list = new ArrayList<String>();
- for (MetaData meta : getMetas(null)) {
- String storyAuthor = meta.getAuthor();
- if (!list.contains(storyAuthor)) {
- list.add(storyAuthor);
- }
- }
-
- Collections.sort(list);
- return list;
+ return getList().getAuthors();
}
/**
- * Return the list of authors, grouped by starting letter(s) if needed.
- * <p>
- * If the number of author is not too high, only one group with an empty
- * name and all the authors will be returned.
- * <p>
- * If not, the authors will be separated into groups:
- * <ul>
- * <li><tt>*</tt>: any author whose name doesn't contain letters nor numbers
- * </li>
- * <li><tt>0-9</tt>: any authors whose name starts with a number</li>
- * <li><tt>A-C</tt> (for instance): any author whose name starts with
- * <tt>A</tt>, <tt>B</tt> or <tt>C</tt></li>
- * </ul>
- * Note that the letters used in the groups can vary (except <tt>*</tt> and
- * <tt>0-9</tt>, which may only be present or not).
- *
- * @return the authors' names, grouped by letter(s)
- *
+ * @return the same as getList()
* @throws IOException
- * in case of IOException
+ * in case of I/O error
+ * @deprecated please use {@link BasicLibrary#getList()} and
+ * {@link MetaResultList#getAuthorsGrouped()} instead.
*/
+ @Deprecated
public Map<String, List<String>> getAuthorsGrouped() throws IOException {
- int MAX = 20;
-
- Map<String, List<String>> groups = new TreeMap<String, List<String>>();
- List<String> authors = getAuthors();
-
- // If all authors fit the max, just report them as is
- if (authors.size() <= MAX) {
- groups.put("", authors);
- return groups;
- }
-
- // Create groups A to Z, which can be empty here
- for (char car = 'A'; car <= 'Z'; car++) {
- groups.put(Character.toString(car), getAuthorsGroup(authors, car));
- }
-
- // Collapse them
- List<String> keys = new ArrayList<String>(groups.keySet());
- for (int i = 0; i + 1 < keys.size(); i++) {
- String keyNow = keys.get(i);
- String keyNext = keys.get(i + 1);
-
- List<String> now = groups.get(keyNow);
- List<String> next = groups.get(keyNext);
-
- int currentTotal = now.size() + next.size();
- if (currentTotal <= MAX) {
- String key = keyNow.charAt(0) + "-"
- + keyNext.charAt(keyNext.length() - 1);
-
- List<String> all = new ArrayList<String>();
- 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)
- }
- }
-
- // Add "special" groups
- groups.put("*", getAuthorsGroup(authors, '*'));
- groups.put("0-9", getAuthorsGroup(authors, '0'));
-
- // Prune empty groups
- keys = new ArrayList<String>(groups.keySet());
- for (String key : keys) {
- if (groups.get(key).isEmpty()) {
- groups.remove(key);
- }
- }
-
- return groups;
- }
-
- /**
- * Get all the authors that start with the given character:
- * <ul>
- * <li><tt>*</tt>: any author whose name doesn't contain letters nor numbers
- * </li>
- * <li><tt>0</tt>: any authors whose name starts with a number</li>
- * <li><tt>A</tt> (any capital latin letter): any author whose name starts
- * with <tt>A</tt></li>
- * </ul>
- *
- * @param authors
- * the full list of authors
- * @param car
- * the starting character, <tt>*</tt>, <tt>0</tt> or a capital
- * letter
- *
- * @return the authors that fulfil the starting letter
- */
- private List<String> getAuthorsGroup(List<String> authors, char car) {
- List<String> accepted = new ArrayList<String>();
- for (String author : authors) {
- char first = '*';
- for (int i = 0; first == '*' && i < author.length(); i++) {
- String san = StringUtils.sanitize(author, true, true);
- char c = san.charAt(i);
- if (c >= '0' && c <= '9') {
- first = '0';
- } else if (c >= 'a' && c <= 'z') {
- first = (char) (c - 'a' + 'A');
- } else if (c >= 'A' && c <= 'Z') {
- first = c;
- }
- }
-
- if (first == car) {
- accepted.add(author);
- }
- }
-
- return accepted;
+ return getList().getAuthorsGrouped();
}
/**
* @throws IOException
* in case of IOException
*/
- public synchronized Story getStory(String luid, Progress pg)
- throws IOException {
+ public Story getStory(String luid, Progress pg) throws IOException {
Progress pgMetas = new Progress();
Progress pgStory = new Progress();
if (pg != null) {
}
Story story = save(support.process(pgProcess), pgSave);
- pg.setName(story.getMeta().getTitle());
pg.done();
return story.getMeta();
pg.setName("Saving story");
if (luid == null || luid.isEmpty()) {
- meta.setLuid(String.format("%03d", getNextId()));
+ meta.setLuid(getNextId());
} else {
meta.setLuid(luid);
}
pg.done();
}
+
+ /**
+ * Describe a {@link Story} from its {@link MetaData} and return a list of
+ * title/value that represent this {@link Story}.
+ *
+ * @param meta
+ * the {@link MetaData} to represent
+ *
+ * @return the information, translated and sorted
+ */
+ static public Map<String, String> getMetaDesc(MetaData meta) {
+ Map<String, String> metaDesc = new LinkedHashMap<String, String>();
+
+ // TODO: i18n
+
+ StringBuilder tags = new StringBuilder();
+ for (String tag : meta.getTags()) {
+ if (tags.length() > 0) {
+ tags.append(", ");
+ }
+ tags.append(tag);
+ }
+
+ // TODO: i18n
+ metaDesc.put("Author", meta.getAuthor());
+ metaDesc.put("Published on", meta.getPublisher());
+ metaDesc.put("Publication date", meta.getDate());
+ metaDesc.put("Creation date", meta.getCreationDate());
+ String count = "";
+ if (meta.getWords() > 0) {
+ count = StringUtils.formatNumber(meta.getWords());
+ }
+ if (meta.isImageDocument()) {
+ metaDesc.put("Number of images", count);
+ } else {
+ metaDesc.put("Number of words", count);
+ }
+ metaDesc.put("Source", meta.getSource());
+ metaDesc.put("Subject", meta.getSubject());
+ metaDesc.put("Language", meta.getLang());
+ metaDesc.put("Tags", tags.toString());
+ metaDesc.put("URL", meta.getUrl());
+
+ return metaDesc;
+ }
}