Beta2 relase
[jvcard.git] / src / be / nikiroo / jvcard / Card.java
index 65ab6fa5225b91fdacdd3430fdc52abdbb317395..53ae972a5803d38482333acae7e7fe565e45e34d 100644 (file)
@@ -3,9 +3,11 @@ package be.nikiroo.jvcard;
 import java.io.BufferedReader;
 import java.io.BufferedWriter;
 import java.io.File;
-import java.io.FileReader;
+import java.io.FileInputStream;
 import java.io.FileWriter;
 import java.io.IOException;
+import java.io.InputStreamReader;
+import java.security.InvalidParameterException;
 import java.util.Arrays;
 import java.util.LinkedList;
 import java.util.List;
@@ -25,29 +27,105 @@ public class Card {
        private File file;
        private boolean dirty;
        private String name;
+       private Format format;
 
+       /**
+        * Create a new {@link Card} from the given {@link File} and {@link Format}.
+        * 
+        * @param file
+        *            the file containing the {@link Card} data, must not be NULL
+        * @param format
+        *            the {@link Format} to use to parse it
+        * 
+        * @throws IOException
+        *             in case of IO error
+        * @throws NullPointerException
+        *             if file is NULL
+        * @throws InvalidParameterException
+        *             if format is NULL
+        */
        public Card(File file, Format format) throws IOException {
                this.file = file;
+               this.format = format;
+               this.name = file.getName();
 
-               if (file != null) {
-                       name = file.getName();
-               }
-
-               BufferedReader buffer = new BufferedReader(new FileReader(file));
+               BufferedReader buffer = new BufferedReader(new InputStreamReader(
+                               new FileInputStream(file), "UTF-8"));
                List<String> lines = new LinkedList<String>();
                for (String line = buffer.readLine(); line != null; line = buffer
                                .readLine()) {
                        lines.add(line);
                }
+               buffer.close();
 
                load(lines, format);
-               dirty = false; // initial load, so no change yet
+               dirty = false; // initial load, so no change yet, so no need to call
+                                               // setPristine()
+       }
+
+       /**
+        * Return the number of {@link Contact} present in this {@link Card}.
+        * 
+        * @return the number of {@link Contact}s
+        */
+       public int size() {
+               return contacts.size();
        }
 
-       public List<Contact> getContacts() {
-               return contacts;
+       /**
+        * Return the {@link Contact} at index <i>index</i>.
+        * 
+        * @param index
+        *            the index of the {@link Contact} to find
+        * 
+        * @return the {@link Contact}
+        * 
+        * @throws IndexOutOfBoundsException
+        *             if the index is < 0 or >= {@link Card#size()}
+        */
+       public Contact get(int index) {
+               return contacts.get(index);
+       }
+       
+       /**
+        * Add a new {@link Contact} in this {@link Card}.
+        * 
+        * @param contact
+        *            the new contact
+        */
+       public void add(Contact contact) {
+               contact.setParent(this);
+               contact.setDirty();
+               contacts.add(contact);
        }
 
+       /**
+        * Remove the given {@link Contact} from its this {@link Card} if it is in.
+        * 
+        * @return TRUE in case of success
+        */
+       public boolean remove(Contact contact) {
+               if (contacts.remove(contact)) {
+                       setDirty();
+               }
+
+               return false;
+       }
+
+       /**
+        * Save the {@link Card} to the given {@link File} with the given
+        * {@link Format}.
+        * 
+        * @param file
+        *            the {@link File} to save to
+        * @param format
+        *            the {@link Format} to use
+        * 
+        * @return TRUE if it was saved
+        * 
+        * @throws IOException
+        *             in case of IO errors
+        */
        public boolean saveAs(File file, Format format) throws IOException {
                if (file == null)
                        return false;
@@ -57,30 +135,83 @@ public class Card {
                writer.close();
 
                if (file.equals(this.file)) {
-                       dirty = false;
+                       setPristine();
                }
 
                return true;
        }
 
-       public boolean save(Format format, boolean bKeys) throws IOException {
+       /**
+        * Save the {@link Card} to the original {@link File} it was open from.
+        * 
+        * @return TRUE if it was saved
+        * 
+        * @throws IOException
+        *             in case of IO errors
+        */
+       public boolean save() throws IOException {
                return saveAs(file, format);
        }
 
+       /**
+        * Return a {@link String} representation of this {@link Card} in the given
+        * {@link Format}.
+        * 
+        * @param format
+        *            the {@link Format} to use
+        * 
+        * @return the {@link String}
+        */
        public String toString(Format format) {
                return Parser.toString(this, format);
        }
 
+       /**
+        * Check if this {@link Card} has unsaved changes.
+        * 
+        * @return TRUE if it has
+        */
+       public boolean isDirty() {
+               return dirty;
+       }
+
+       /**
+        * Return the name of this card (the name of the {@link File} which it was
+        * opened from).
+        * 
+        * @return the name
+        */
+       public String getName() {
+               return name;
+       }
+
+       @Override
        public String toString() {
                return toString(Format.VCard21);
        }
 
+       /**
+        * Load the given data from the given {@link Format} in this {@link Card}.
+        * 
+        * @param serializedContent
+        *            the data
+        * @param format
+        *            the {@link Format}
+        */
        protected void load(String serializedContent, Format format) {
                // note: fixed size array
                List<String> lines = Arrays.asList(serializedContent.split("\n"));
                load(lines, format);
        }
 
+       /**
+        * Load the given data from the given {@link Format} in this {@link Card}.
+        * 
+        * @param lines
+        *            the data
+        * @param format
+        *            the {@link Format}
+        */
        protected void load(List<String> lines, Format format) {
                this.contacts = Parser.parse(lines, format);
                setDirty();
@@ -90,23 +221,21 @@ public class Card {
                }
        }
 
-       public boolean isDirty() {
-               return dirty;
-       }
-
        /**
-        * Return the name of this card.
-        * 
-        * @return the name
+        * Notify that this element has unsaved changes.
         */
-       public String getName() {
-               return name;
+       void setDirty() {
+               dirty = true;
        }
 
        /**
-        * Notify that this element has unsaved changes.
+        * Notify this element <i>and all its descendants</i> that it is in pristine
+        * state (as opposed to dirty).
         */
-       void setDirty() {
-               dirty = true;
+       void setPristine() {
+               dirty = false;
+               for (Contact contact : contacts) {
+                       contact.setPristine();
+               }
        }
 }