Beta2 relase
[jvcard.git] / src / be / nikiroo / jvcard / Contact.java
index 643631314d0adbbdb06356991238e2195647fd8a..c5579fe8c5e1cf4a71eeec149d83c7d23be79ff4 100644 (file)
@@ -7,6 +7,7 @@ import java.util.Map;
 
 import be.nikiroo.jvcard.parsers.Format;
 import be.nikiroo.jvcard.parsers.Parser;
+import be.nikiroo.jvcard.tui.StringUtils;
 
 /**
  * A contact is the information that represent a contact person or organisation.
@@ -33,15 +34,17 @@ public class Contact {
 
                boolean fn = false;
                boolean n = false;
-               for (Data data : content) {
-                       if (data.getName().equals("N")) {
-                               n = true;
-                       } else if (data.getName().equals("FN")) {
-                               fn = true;
-                       }
+               if (content != null) {
+                       for (Data data : content) {
+                               if (data.getName().equals("N")) {
+                                       n = true;
+                               } else if (data.getName().equals("FN")) {
+                                       fn = true;
+                               }
 
-                       if (!data.getName().equals("VERSION")) {
-                               datas.add(data);
+                               if (!data.getName().equals("VERSION")) {
+                                       datas.add(data);
+                               }
                        }
                }
 
@@ -57,12 +60,53 @@ public class Contact {
        }
 
        /**
-        * Return the informations (note: this is the actual list, be careful).
+        * Return the number of {@link Data} present in this {@link Contact}.
         * 
-        * @return the list of data anout this contact
+        * @return the number of {@link Data}s
+        */
+       public int size() {
+               return datas.size();
+       }
+
+       /**
+        * Return the {@link Data} at index <i>index</i>.
+        * 
+        * @param index
+        *            the index of the {@link Data} to find
+        * 
+        * @return the {@link Data}
+        * 
+        * @throws IndexOutOfBoundsException
+        *             if the index is < 0 or >= {@link Contact#size()}
+        */
+       public Data get(int index) {
+               return datas.get(index);
+       }
+
+       /**
+        * Add a new {@link Data} in this {@link Contact}.
+        * 
+        * @param data
+        *            the new data
+        */
+       public void add(Data data) {
+               data.setParent(this);
+               data.setDirty();
+               datas.add(data);
+       }
+
+       /**
+        * Remove the given {@link Data} from its this {@link Contact} if it is in.
+        * 
+        * @return TRUE in case of success
         */
-       public List<Data> getContent() {
-               return datas;
+       public boolean remove(Data data) {
+               if (datas.remove(data)) {
+                       setDirty();
+                       return true;
+               }
+
+               return false;
        }
 
        /**
@@ -77,7 +121,8 @@ public class Contact {
                for (Data data : getData(name)) {
                        if (first == null)
                                first = data;
-                       for (TypeInfo type : data.getTypes()) {
+                       for (int index = 0; index < data.size(); index++) {
+                               TypeInfo type = data.get(index);
                                if (type.getName().equals("TYPE")
                                                && type.getValue().equals("pref")) {
                                        return data;
@@ -155,7 +200,7 @@ public class Contact {
         * @return the {@link String} representation
         */
        public String toString(String format) {
-               return toString(format, "|", null, -1);
+               return toString(format, "|", null, -1, true, false);
        }
 
        /**
@@ -165,7 +210,7 @@ public class Contact {
         * The format is basically a list of field names separated by a pipe and
         * optionally parametrised. The parameters allows you to:
         * <ul>
-        * <li>@x: show only a present/not present info</li>
+        * <li>@x: (the 'x' is the letter 'x') show only a present/not present info</li>
         * <li>@n: limit the size to a fixed value 'n'</li>
         * <li>@+: expand the size of this field as much as possible</li>
         * </ul>
@@ -181,13 +226,17 @@ public class Contact {
         * @param width
         *            a fixed width or -1 for "as long as needed"
         * 
+        * @param unicode
+        *            allow Uniode or only ASCII characters
+        * 
         * @return the {@link String} representation
         */
        public String toString(String format, String separator, String padding,
-                       int width) {
+                       int width, boolean unicode, boolean removeAccents) {
                StringBuilder builder = new StringBuilder();
 
-               for (String str : toStringArray(format, separator, padding, width)) {
+               for (String str : toStringArray(format, separator, padding, width,
+                               unicode)) {
                        builder.append(str);
                }
 
@@ -217,10 +266,13 @@ public class Contact {
         * @param width
         *            a fixed width or -1 for "as long as needed"
         * 
+        * @param unicode
+        *            allow Uniode or only ASCII characters
+        * 
         * @return the {@link String} representation
         */
        public String[] toStringArray(String format, String separator,
-                       String padding, int width) {
+                       String padding, int width, boolean unicode) {
                if (width > -1) {
                        int numOfFields = format.split("\\|").length;
                        if (separator != null)
@@ -235,7 +287,7 @@ public class Contact {
                List<String> str = new LinkedList<String>();
 
                boolean first = true;
-               for (String s : toStringArray(format, width)) {
+               for (String s : toStringArray(format, width, unicode)) {
                        if (!first) {
                                str.add(separator);
                        }
@@ -269,10 +321,12 @@ public class Contact {
         *            the format to use
         * @param width
         *            a fixed width or -1 for "as long as needed"
-        * 
+        * @param unicode
+        *            allow Uniode or only ASCII characters
+        *
         * @return the {@link String} representation
         */
-       public String[] toStringArray(String format, int width) {
+       public String[] toStringArray(String format, int width, boolean unicode) {
                List<String> str = new LinkedList<String>();
 
                String[] formatFields = format.split("\\|");
@@ -318,11 +372,14 @@ public class Contact {
                        }
 
                        String value = getPreferredDataValue(field);
-                       if (value == null)
+                       if (value == null) {
                                value = "";
+                       } else {
+                               value = StringUtils.sanitize(value, unicode);
+                       }
 
                        if (size > -1) {
-                               value = fixedString(value, size);
+                               value = StringUtils.padString(value, size);
                        }
 
                        expandedFields[i] = expand;
@@ -371,11 +428,13 @@ public class Contact {
                                for (int i = 0; i < values.length; i++) {
                                        if (expandedFields[i]) {
                                                if (remainder > 0) {
-                                                       values[i] = values[i] + fixedString("", remainder);
+                                                       values[i] = values[i]
+                                                                       + StringUtils.padString("", remainder);
                                                        remainder = 0;
                                                }
                                                if (padPerItem > 0) {
-                                                       values[i] = values[i] + fixedString("", padPerItem);
+                                                       values[i] = values[i]
+                                                                       + StringUtils.padString("", padPerItem);
                                                }
                                        }
                                }
@@ -392,72 +451,6 @@ public class Contact {
                return str.toArray(new String[] {});
        }
 
-       /**
-        * Fix the size of the given {@link String} either with space-padding or by
-        * shortening it.
-        * 
-        * @param string
-        *            the {@link String} to fix
-        * @param size
-        *            the size of the resulting {@link String}
-        * 
-        * @return the fixed {@link String} of size <i>size</i>
-        */
-       static private String fixedString(String string, int size) {
-               int length = string.length();
-
-               if (length > size) {
-                       string = string.substring(0, size);
-               } else if (length < size) {
-                       string = string
-                                       + new String(new char[size - length]).replace('\0', ' ');
-               }
-
-               return string;
-       }
-
-       /**
-        * Add a {@link String} to the given {@link List}, but make sure it does not
-        * exceed the maximum size, and truncate it if needed to fit.
-        * 
-        * @param list
-        * @param add
-        * @param currentSize
-        * @param maxSize
-        * @return
-        */
-       static private int addToList(List<String> list, String add,
-                       int currentSize, int maxSize) {
-               if (add == null || add.length() == 0) {
-                       if (add != null)
-                               list.add(add);
-                       return 0;
-               }
-
-               if (maxSize > -1) {
-                       if (currentSize < maxSize) {
-                               if (currentSize + add.length() >= maxSize) {
-                                       add = add.substring(0, maxSize - currentSize);
-                               }
-                       } else {
-                               add = "";
-                       }
-               }
-
-               list.add(add);
-               return add.length();
-       }
-
-       /**
-        * Return a {@link String} representation of this contact, in vCard 2.1,
-        * without BKeys.
-        * 
-        * @return the {@link String} representation
-        */
-       public String toString() {
-               return toString(Format.VCard21, -1);
-       }
-
        /**
         * Update the information from this contact with the information in the
         * given contact. Non present fields will be removed, new fields will be
@@ -488,6 +481,39 @@ public class Contact {
                setDirty();
        }
 
+       /**
+        * Delete this {@link Contact} from its parent {@link Card} if any.
+        * 
+        * @return TRUE in case of success
+        */
+       public boolean delete() {
+               if (parent != null) {
+                       return parent.remove(this);
+               }
+
+               return false;
+       }
+
+       /**
+        * Check if this {@link Contact} has unsaved changes.
+        * 
+        * @return TRUE if it has
+        */
+       public boolean isDirty() {
+               return dirty;
+       }
+
+       /**
+        * Return a {@link String} representation of this contact, in vCard 2.1,
+        * without BKeys.
+        * 
+        * @return the {@link String} representation
+        */
+       @Override
+       public String toString() {
+               return toString(Format.VCard21, -1);
+       }
+
        /**
         * Mark all the binary fields with a BKey number.
         * 
@@ -512,10 +538,6 @@ public class Contact {
                }
        }
 
-       public boolean isDirty() {
-               return dirty;
-       }
-
        /**
         * Notify that this element has unsaved changes, and notify its parent of
         * the same if any.
@@ -526,41 +548,60 @@ public class Contact {
                        this.parent.setDirty();
        }
 
+       /**
+        * Notify this element <i>and all its descendants</i> that it is in pristine
+        * state (as opposed to dirty).
+        */
+       void setPristine() {
+               dirty = false;
+               for (Data data : datas) {
+                       data.setPristine();
+               }
+       }
+
+       /**
+        * Set the parent of this {@link Contact} <i>and all its descendants</i>.
+        * 
+        * @param parent
+        *            the new parent
+        */
        void setParent(Card parent) {
                this.parent = parent;
                for (Data data : datas) {
                        data.setParent(this);
                }
        }
-       
+
        /**
-        * Delete this {@link Contact} from its parent {@link Card} if any.
+        * Add a {@link String} to the given {@link List}, but make sure it does not
+        * exceed the maximum size, and truncate it if needed to fit.
         * 
-        * @return TRUE in case of success
+        * @param list
+        * @param add
+        * @param currentSize
+        * @param maxSize
+        * @return
         */
-       public boolean delete() {
-               if (parent != null) {
-                       List<Contact> list = parent.getContactsList();
-                       for (int i = 0; i < list.size(); i++) {
-                               if (list.get(i) == this) {
-                                       list.remove(i);
-                                       parent.setDirty();
-                                       return true;
+       static private int addToList(List<String> list, String add,
+                       int currentSize, int maxSize) {
+               if (add == null || add.length() == 0) {
+                       if (add != null)
+                               list.add(add);
+                       return 0;
+               }
+
+               if (maxSize > -1) {
+                       if (currentSize < maxSize) {
+                               if (currentSize + add.length() >= maxSize) {
+                                       add = add.substring(0, maxSize - currentSize);
                                }
+                       } else {
+                               add = "";
                        }
                }
 
-               return false;
+               list.add(add);
+               return add.length();
        }
 
-       /**
-        * Notify this element <i>and all its descendants</i> that it is in pristine
-        * state (as opposed to dirty).
-        */
-       void setPristine() {
-               dirty = false;
-               for (Data data: datas) {
-                       data.setPristine();
-               }
-       }
 }