code cleanup / jdoc
[nikiroo-utils.git] / src / be / nikiroo / fanfix / data / MetaData.java
index 3980e96bc77b8ad359bee903381633daf832e3f4..1c6ad42838d5541dbd69533b9fb1e2d21d52dd60 100644 (file)
@@ -1,28 +1,52 @@
 package be.nikiroo.fanfix.data;
 
-import java.awt.image.BufferedImage;
+import java.io.Serializable;
+import java.util.ArrayList;
 import java.util.List;
 
+import be.nikiroo.fanfix.supported.SupportType;
+import be.nikiroo.utils.Image;
+import be.nikiroo.utils.StringUtils;
+
 /**
  * The meta data associated to a {@link Story} object.
+ * <p>
+ * Note that some earlier version of the program did not save the resume as an
+ * external file; for those stories, the resume is not fetched until the story
+ * is.
+ * <p>
+ * The cover is never fetched until the story is.
  * 
  * @author niki
  */
-public class MetaData {
+public class MetaData implements Cloneable, Comparable<MetaData>, Serializable {
+       private static final long serialVersionUID = 1L;
+
        private String title;
        private String author;
        private String date;
        private Chapter resume;
        private List<String> tags;
-       private BufferedImage cover;
+       private Image cover;
        private String subject;
        private String source;
+       private String url;
        private String uuid;
        private String luid;
        private String lang;
        private String publisher;
+       private String type;
        private boolean imageDocument;
+       private long words;
+       private String creationDate;
+       private boolean fakeCover;
 
+       /**
+        * Create an empty {@link MetaData}.
+        */
+       public MetaData() {
+       }
+       
        /**
         * The title of the story.
         * 
@@ -62,7 +86,7 @@ public class MetaData {
        }
 
        /**
-        * The story publication date.
+        * The story publication date, we try to use "YYYY-mm-dd" when possible.
         * 
         * @return the date
         */
@@ -71,7 +95,7 @@ public class MetaData {
        }
 
        /**
-        * The story publication date.
+        * The story publication date, we try to use "YYYY-mm-dd" when possible.
         * 
         * @param date
         *            the date to set
@@ -101,6 +125,12 @@ public class MetaData {
 
        /**
         * The story resume (a.k.a. description).
+        * <p>
+        * This can be NULL if we don't have a resume for this {@link Story}.
+        * <p>
+        * Note that some earlier version of the program did not save the resume as
+        * an external file; for those stories, the resume is not fetched until the
+        * story is.
         * 
         * @return the resume
         */
@@ -110,6 +140,10 @@ public class MetaData {
 
        /**
         * The story resume (a.k.a. description).
+        * <p>
+        * Note that some earlier version of the program did not save the resume as
+        * an external file; for those stories, the resume is not fetched until the
+        * story is.
         * 
         * @param resume
         *            the resume to set
@@ -119,26 +153,30 @@ public class MetaData {
        }
 
        /**
-        * The cover image of the story if any (can be NULL).
+        * The cover image of the story, if any (can be NULL).
+        * <p>
+        * The cover is not fetched until the story is.
         * 
         * @return the cover
         */
-       public BufferedImage getCover() {
+       public Image getCover() {
                return cover;
        }
 
        /**
-        * The cover image of the story if any (can be NULL).
+        * The cover image of the story, if any (can be NULL).
+        * <p>
+        * The cover is not fetched until the story is.
         * 
         * @param cover
         *            the cover to set
         */
-       public void setCover(BufferedImage cover) {
+       public void setCover(Image cover) {
                this.cover = cover;
        }
 
        /**
-        * The subject of the story (or instance, if it is a fanfiction, what is the
+        * The subject of the story (for instance, if it is a fanfiction, what is the
         * original work; if it is a technical text, what is the technical
         * subject...).
         * 
@@ -161,7 +199,11 @@ public class MetaData {
        }
 
        /**
-        * The source of this story (where it was downloaded from).
+        * The source of this story -- a very user-visible piece of data.
+        * <p>
+        * It is initialised with the same value as {@link MetaData#getPublisher()},
+        * but the user is allowed to change it into any value -- this is a sort of
+        * 'category'.
         * 
         * @return the source
         */
@@ -170,7 +212,11 @@ public class MetaData {
        }
 
        /**
-        * The source of this story (where it was downloaded from).
+        * The source of this story -- a very user-visible piece of data.
+        * <p>
+        * It is initialised with the same value as {@link MetaData#getPublisher()},
+        * but the user is allowed to change it into any value -- this is a sort of
+        * 'category'.
         * 
         * @param source
         *            the source to set
@@ -180,7 +226,26 @@ public class MetaData {
        }
 
        /**
-        * A unique value representing the story (it is often an URL).
+        * The original URL from which this {@link Story} was imported.
+        * 
+        * @return the url
+        */
+       public String getUrl() {
+               return url;
+       }
+
+       /**
+        * The original URL from which this {@link Story} was imported.
+        * 
+        * @param url
+        *            the new url to set
+        */
+       public void setUrl(String url) {
+               this.url = url;
+       }
+
+       /**
+        * A unique value representing the story (it is often a URL).
         * 
         * @return the uuid
         */
@@ -189,7 +254,7 @@ public class MetaData {
        }
 
        /**
-        * A unique value representing the story (it is often an URL).
+        * A unique value representing the story (it is often a URL).
         * 
         * @param uuid
         *            the uuid to set
@@ -199,7 +264,14 @@ public class MetaData {
        }
 
        /**
-        * A unique value representing the story in the local library.
+        * A unique value representing the story in the local library (usually a
+        * numerical value 0-padded with a minimum size of 3; but this is subject to
+        * change and you can also obviously have more than 1000 stories --
+        * <strong>a luid may potentially be anything else, including non-numeric
+        * characters</strong>).
+        * <p>
+        * A NULL or empty luid represents an incomplete, corrupted or fake
+        * {@link Story}.
         * 
         * @return the luid
         */
@@ -208,9 +280,16 @@ public class MetaData {
        }
 
        /**
-        * A unique value representing the story in the local library.
+        * A unique value representing the story in the local library (usually a
+        * numerical value 0-padded with a minimum size of 3; but this is subject to
+        * change and you can also obviously have more than 1000 stories --
+        * <strong>a luid may potentially be anything else, including non-numeric
+        * characters</strong>).
+        * <p>
+        * A NULL or empty luid represents an incomplete, corrupted or fake
+        * {@link Story}.
         * 
-        * @param uuid
+        * @param luid
         *            the luid to set
         */
        public void setLuid(String luid) {
@@ -237,7 +316,15 @@ public class MetaData {
        }
 
        /**
-        * The story publisher (other the same as the source).
+        * The story publisher -- which is also the user representation of the
+        * output type this {@link Story} is in (see {@link SupportType}).
+        * <p>
+        * It allows you to know where the {@link Story} comes from, and is not
+        * supposed to change.
+        * <p>
+        * It's the user representation of the enum
+        * ({@link SupportType#getSourceName()}, not
+        * {@link SupportType#toString()}).
         * 
         * @return the publisher
         */
@@ -246,7 +333,15 @@ public class MetaData {
        }
 
        /**
-        * The story publisher (other the same as the source).
+        * The story publisher -- which is also the user representation of the
+        * output type this {@link Story} is in (see {@link SupportType}).
+        * <p>
+        * It allows you to know where the {@link Story} comes from, and is not
+        * supposed to change.
+        * <p>
+        * It's the user representation of the enum
+        * ({@link SupportType#getSourceName()}, not
+        * {@link SupportType#toString()}).
         * 
         * @param publisher
         *            the publisher to set
@@ -255,8 +350,45 @@ public class MetaData {
                this.publisher = publisher;
        }
 
+       /**
+        * The output type this {@link Story} is in (see {@link SupportType}).
+        * <p>
+        * It allows you to know where the {@link Story} comes from, and is not
+        * supposed to change.
+        * <p>
+        * It's the direct representation of the enum
+        * ({@link SupportType#toString()}, not
+        * {@link SupportType#getSourceName()}).
+        * 
+        * @return the type the type
+        */
+       public String getType() {
+               return type;
+       }
+
+       /**
+        * The output type this {@link Story} is in (see {@link SupportType}).
+        * <p>
+        * It allows you to know where the {@link Story} comes from, and is not
+        * supposed to change.
+        * <p>
+        * It's the direct representation of the enum
+        * ({@link SupportType#toString()}, not
+        * {@link SupportType#getSourceName()}).
+        * 
+        * @param type
+        *            the new type to set
+        */
+       public void setType(String type) {
+               this.type = type;
+       }
+
        /**
         * Document catering mostly to image files.
+        * <p>
+        * I.E., this is a comics or a manga, not a textual story with actual words.
+        * <p>
+        * In image documents, all the paragraphs are supposed to be images.
         * 
         * @return the imageDocument state
         */
@@ -266,6 +398,10 @@ public class MetaData {
 
        /**
         * Document catering mostly to image files.
+        * <p>
+        * I.E., this is a comics or a manga, not a textual story with actual words.
+        * <p>
+        * In image documents, all the paragraphs are supposed to be images.
         * 
         * @param imageDocument
         *            the imageDocument state to set
@@ -273,4 +409,168 @@ public class MetaData {
        public void setImageDocument(boolean imageDocument) {
                this.imageDocument = imageDocument;
        }
+
+       /**
+        * The number of words (or images if this is an image document -- see
+        * {@link MetaData#isImageDocument()}) in the related {@link Story}.
+        * 
+        * @return the number of words/images
+        */
+       public long getWords() {
+               return words;
+       }
+
+       /**
+        * The number of words (or images if this is an image document -- see
+        * {@link MetaData#isImageDocument()}) in the related {@link Story}.
+        * 
+        * @param words
+        *            the number of words/images to set
+        */
+       public void setWords(long words) {
+               this.words = words;
+       }
+
+       /**
+        * The (Fanfix) {@link Story} creation date, i.e., when the {@link Story}
+        * was fetched via Fanfix.
+        * 
+        * @return the creation date
+        */
+       public String getCreationDate() {
+               return creationDate;
+       }
+
+       /**
+        * The (Fanfix) {@link Story} creation date, i.e., when the {@link Story}
+        * was fetched via Fanfix.
+        * 
+        * @param creationDate
+        *            the creation date to set
+        */
+       public void setCreationDate(String creationDate) {
+               this.creationDate = creationDate;
+       }
+
+       /**
+        * The cover in this {@link MetaData} object is "fake", in the sense that it
+        * comes from the actual content images.
+        * 
+        * @return TRUE for a fake cover
+        */
+       public boolean isFakeCover() {
+               return fakeCover;
+       }
+
+       /**
+        * The cover in this {@link MetaData} object is "fake", in the sense that it
+        * comes from the actual content images
+        * 
+        * @param fakeCover
+        *            TRUE for a fake cover
+        */
+       public void setFakeCover(boolean fakeCover) {
+               this.fakeCover = fakeCover;
+       }
+
+       @Override
+       public int compareTo(MetaData o) {
+               if (o == null) {
+                       return 1;
+               }
+
+               String id = (getTitle() == null ? "" : getTitle())
+                               + (getUuid() == null ? "" : getUuid())
+                               + (getLuid() == null ? "" : getLuid());
+               String oId = (getTitle() == null ? "" : o.getTitle())
+                               + (getUuid() == null ? "" : o.getUuid())
+                               + (o.getLuid() == null ? "" : o.getLuid());
+
+               return id.compareToIgnoreCase(oId);
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               if (!(obj instanceof MetaData)) {
+                       return false;
+               }
+
+               return compareTo((MetaData) obj) == 0;
+       }
+
+       @Override
+       public int hashCode() {
+               String uuid = getUuid();
+               if (uuid == null) {
+                       uuid = "" + title + author + source;
+               }
+
+               return uuid.hashCode();
+       }
+
+       @Override
+       public MetaData clone() {
+               MetaData meta = null;
+               try {
+                       meta = (MetaData) super.clone();
+               } catch (CloneNotSupportedException e) {
+                       // Did the clones rebel?
+                       System.err.println(e);
+               }
+
+               if (tags != null) {
+                       meta.tags = new ArrayList<String>(tags);
+               }
+
+               if (resume != null) {
+                       meta.resume = resume.clone();
+               }
+
+               return meta;
+       }
+
+       /**
+        * Display a DEBUG {@link String} representation of this object.
+        * <p>
+        * This is not efficient, nor intended to be.
+        */
+       @Override
+       public String toString() {
+               String title = "";
+               if (getTitle() != null) {
+                       title = getTitle();
+               }
+
+               StringBuilder tags = new StringBuilder();
+               if (getTags() != null) {
+                       for (String tag : getTags()) {
+                               if (tags.length() > 0) {
+                                       tags.append(", ");
+                               }
+                               tags.append(tag);
+                       }
+               }
+
+               String resume = "";
+               if (getResume() != null) {
+                       for (Paragraph para : getResume()) {
+                               resume += "\n\t";
+                               resume += para.toString().substring(0,
+                                               Math.min(para.toString().length(), 120));
+                       }
+                       resume += "\n";
+               }
+
+               String cover = "none";
+               if (getCover() != null) {
+                       cover = StringUtils.formatNumber(getCover().getSize())
+                                       + "bytes";
+               }
+
+               return String.format(
+                               "Meta %s:\n\tTitle: [%s]\n\tAuthor: [%s]\n\tDate: [%s]\n\tTags: [%s]\n\tWord count: [%s]"
+                                               + "\n\tResume: [%s]\n\tCover: [%s]",
+                               luid, title, getAuthor(), getDate(), tags.toString(),
+                               "" + words, resume, cover);
+       }
 }