import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
-import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
-import java.util.ArrayList;
+import java.security.InvalidParameterException;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
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;
-
- if (file != null) {
- name = file.getName();
- }
+ this.name = file.getName();
BufferedReader buffer = new BufferedReader(new InputStreamReader(
new FileInputStream(file), "UTF-8"));
}
/**
- * Return the full list of {@link Contact}s. Please use responsibly (this is
- * the original list, do not modify the list itself).
+ * Return the number of {@link Contact} present in this {@link Card}.
*
- * @return the list of {@link Contact}s
+ * @return the number of {@link Contact}s
*/
- public List<Contact> getContactsList() {
- return contacts;
+ public int size() {
+ return contacts.size();
}
/**
- * Return the list of {@link Contact}s. Note that this list is a copy.
+ * Return the {@link Contact} at index <i>index</i>.
*
- * @return the list of {@link Contact}s
+ * @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 List<Contact> getContacts() {
- ArrayList<Contact> list = new ArrayList<Contact>(size());
- list.addAll(contacts);
- return list;
- }
-
- public int size() {
- return contacts.size();
- }
-
public Contact get(int index) {
return contacts.get(index);
}
+ /**
+ * 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;
return true;
}
+ /**
+ * 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();
}
}
- public boolean isDirty() {
- return dirty;
- }
-
/**
- * Return the name of this card.
+ * Return the full list of {@link Contact}s. Please use responsibly (this is
+ * the original list).
*
- * @return the name
+ * @return the list of {@link Contact}s
*/
- public String getName() {
- return name;
+ List<Contact> getContactsList() {
+ return contacts;
}
/**
}
/**
- * 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 List<Data> getContent() {
- return datas;
+ 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);
}
/**
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;
return str.toArray(new 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
setDirty();
}
+ /**
+ * Delete this {@link Contact} from its parent {@link Card} if any.
+ *
+ * @return TRUE in case of success
+ */
+ 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;
+ }
+ }
+ }
+
+ 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.
*
}
}
- public boolean isDirty() {
- return dirty;
- }
-
/**
* Notify that this element has unsaved changes, and notify its parent of
* the same if any.
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) {
}
/**
- * 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();
- }
- }
}
import java.util.LinkedList;
import java.util.List;
+/**
+ * A data is a piece of information present in a {@link Contact}. It is
+ * basically a key/value pair with optional types and an optional group name.
+ *
+ * @author niki
+ *
+ */
public class Data {
+ public enum DataPart {
+ FN_FAMILY, FN_GIVEN, FN_ADDITIONAL, // Name
+ FN_PRE, FN_POST, // Pre/Post
+ BDAY_YYYY, BDAY_MM, BDAY_DD, // BDay
+ ADR_PBOX, ADR_EXTENDED, ADR_STREET, ADR_CITY, ADR_REGION, ADR_POSTAL_CODE, ADR_COUNTRY
+ // Address
+ }
+
private String name;
private String value;
private String group;
private boolean dirty;
private Contact parent;
+ /**
+ * Create a new {@link Data} with the given values.
+ *
+ * @param types
+ * the types of this {@link Data}
+ * @param name
+ * its name
+ * @param value
+ * its value
+ * @param group
+ * its group if any
+ */
public Data(List<TypeInfo> types, String name, String value, String group) {
if (types == null) {
types = new LinkedList<TypeInfo>();
b64 = -1;
for (TypeInfo type : types) {
+ type.setParent(this);
if (type.getName().equals("ENCODING")
&& type.getValue().equals("b")) {
b64 = 0;
}
}
- public List<TypeInfo> getTypes() {
- return types;
+ /**
+ * Return the number of {@link TypeInfo} present in this {@link Data}.
+ *
+ * @return the number of {@link TypeInfo}s
+ */
+ public int size() {
+ return types.size();
}
+ /**
+ * Return the {@link TypeInfo} at index <i>index</i>.
+ *
+ * @param index
+ * the index of the {@link TypeInfo} to find
+ *
+ * @return the {@link TypeInfo}
+ *
+ * @throws IndexOutOfBoundsException
+ * if the index is < 0 or >= {@link Data#size()}
+ */
+ public TypeInfo get(int index) {
+ return types.get(index);
+ }
+
+ /**
+ * Return the name of this {@link Data}
+ *
+ * @return the name
+ */
public String getName() {
return name;
}
+ /**
+ * Return the value of this {@link Data}
+ *
+ * @return the value
+ */
public String getValue() {
return value;
}
+ /**
+ * Change the value of this {@link Data}
+ *
+ * @param value
+ * the new value
+ */
public void setValue(String value) {
if ((value == null && this.value != null)
|| (value != null && !value.equals(this.value))) {
}
}
+ /**
+ * Return the group of this {@link Data}
+ *
+ * @return the group
+ */
public String getGroup() {
return group;
}
+ /**
+ * Return the bkey number of this {@link Data} or -1 if it is not binary.
+ *
+ * @return the bkey or -1
+ */
public int getB64Key() {
return b64;
}
+ /**
+ * Change the bkey of this {@link Data}
+ *
+ * @param i
+ * the new bkey
+ *
+ * @throw InvalidParameterException if the {@link Data} is not binary or if
+ * it is but you try to set a negative bkey
+ */
void resetB64Key(int i) {
if (!isBinary())
throw new InvalidParameterException(
b64 = i;
}
+ /**
+ * Check if this {@link Data} is binary
+ *
+ * @return TRUE if it is
+ */
public boolean isBinary() {
return b64 >= 0;
}
+ /**
+ * Check if this {@link Data} has unsaved changes.
+ *
+ * @return TRUE if it has
+ */
public boolean isDirty() {
return dirty;
}
void setPristine() {
dirty = false;
for (TypeInfo type : types) {
- // TODO ?
+ type.setPristine();
}
}
+ /**
+ * Set the parent of this {@link Data}.
+ *
+ * @param parent
+ * the new parent
+ */
void setParent(Contact parent) {
this.parent = parent;
}
-
}
+++ /dev/null
-package be.nikiroo.jvcard;
-
-public enum DataPart {
- FN_FAMILY, FN_GIVEN, FN_ADDITIONAL, // Name
- FN_PRE, FN_POST, // Pre/Post
- BDAY_YYYY, BDAY_MM, BDAY_DD, // BDay
- ADR_PBOX, ADR_EXTENDED, ADR_STREET, ADR_CITY, ADR_REGION, ADR_POSTAL_CODE, ADR_COUNTRY
- // Address
-}
public class TypeInfo {
private String name;
private String value;
+ private Data parent;
+ private boolean dirty;
public TypeInfo(String name, String value) {
this.name = name;
public String getValue() {
return value;
}
+
+ /**
+ * Check if this {@link TypeInfo} has unsaved changes.
+ *
+ * @return TRUE if it has
+ */
+ public boolean isDirty() {
+ return dirty;
+ }
+
+ /**
+ * Notify that this element has unsaved changes, and notify its parent of
+ * the same if any.
+ */
+ protected void setDirty() {
+ this.dirty = true;
+ if (this.parent != null)
+ 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;
+ }
+
+ /**
+ * Set the parent of this {@link TypeInfo}.
+ *
+ * @param parent
+ * the new parent
+ */
+ void setParent(Data parent) {
+ this.parent = parent;
+ }
}
\ No newline at end of file
public class AbookParser {
public static List<Contact> parse(List<String> lines) {
List<Contact> contacts = new LinkedList<Contact>();
-
+
for (String line : lines) {
List<Data> content = new LinkedList<Data>();
// note: save as pine means normal LN, nor CRLN
builder.append('\n');
-
+
return builder.toString();
}
public static String toString(Card card) {
StringBuilder builder = new StringBuilder();
- for (Contact contact : card.getContactsList()) {
- builder.append(toString(contact, -1));
+ for (int index = 0; index < card.size(); index++) {
+ builder.append(toString(card.get(index), -1));
}
return builder.toString();
builder.append("\r\n");
builder.append("VERSION:2.1");
builder.append("\r\n");
- for (Data data : contact.getContent()) {
+ for (int indexData = 0; indexData < contact.size(); indexData++) {
+ Data data = contact.get(indexData);
if (data.getGroup() != null && !data.getGroup().trim().equals("")) {
builder.append(data.getGroup().trim());
builder.append('.');
}
builder.append(data.getName());
- for (TypeInfo type : data.getTypes()) {
+ for (int indexType = 0; indexType < data.size(); indexType++) {
+ TypeInfo type = data.get(indexType);
builder.append(';');
builder.append(type.getName());
if (type.getValue() != null
public static String toString(Card card) {
StringBuilder builder = new StringBuilder();
- for (Contact contact : card.getContactsList()) {
- builder.append(toString(contact, -1));
+ for (int index = 0; index < card.size(); index++) {
+ builder.append(toString(card.get(index), -1));
}
-
+
builder.append("\r\n");
return builder.toString();
if (photo != null) {
TypeInfo encoding = null;
TypeInfo type = null;
- for (TypeInfo info : photo.getTypes()) {
+ for (int index = 0; index < photo.size(); index++) {
+ TypeInfo info = photo.get(index);
if (info.getName() != null) {
if (info.getName().equalsIgnoreCase("ENCODING"))
encoding = info;
import java.util.LinkedList;
import java.util.List;
-import com.googlecode.lanterna.input.KeyType;
-
import be.nikiroo.jvcard.Contact;
import be.nikiroo.jvcard.Data;
import be.nikiroo.jvcard.TypeInfo;
import be.nikiroo.jvcard.i18n.Trans;
import be.nikiroo.jvcard.tui.KeyAction;
-import be.nikiroo.jvcard.tui.UiColors;
import be.nikiroo.jvcard.tui.KeyAction.DataType;
import be.nikiroo.jvcard.tui.KeyAction.Mode;
import be.nikiroo.jvcard.tui.StringUtils;
+import be.nikiroo.jvcard.tui.UiColors;
import be.nikiroo.jvcard.tui.UiColors.Element;
+import com.googlecode.lanterna.input.KeyType;
+
public class ContactDetailsRaw extends MainContentList {
private Contact contact;
private int mode;
this.contact = contact;
this.mode = 0;
- for (int i = 0; i < contact.getContent().size(); i++) {
+ for (int i = 0; i < contact.size(); i++) {
addItem("[detail line]");
}
}
Element elDirty = (focused && selected) ? Element.CONTACT_LINE_DIRTY_SELECTED
: Element.CONTACT_LINE_DIRTY;
- Data data = contact.getContent().get(index);
+ Data data = contact.get(index);
List<TextPart> parts = new LinkedList<TextPart>();
if (data.isDirty()) {
}
break;
case 1:
- for (TypeInfo type : data.getTypes()) {
+ for (int indexType = 0; indexType < data.size(); indexType++) {
+ TypeInfo type = data.get(indexType);
if (valueBuilder.length() > 1)
valueBuilder.append(", ");
valueBuilder.append(type.getName());
List<KeyAction> actions = new LinkedList<KeyAction>();
// TODO: add, remove
- actions.add(new KeyAction(Mode.ASK_USER , KeyType.Enter,
+ actions.add(new KeyAction(Mode.ASK_USER, KeyType.Enter,
Trans.StringId.DUMMY) {
@Override
public Object getObject() {
- return contact.getContent().get(getSelectedIndex());
+ return contact.get(getSelectedIndex());
}
@Override
this.contacts = new LinkedList<Contact>();
if (card != null) {
- for (int i = 0; i < card.getContacts().size(); i++) {
- Contact c = card.getContacts().get(i);
+ for (int i = 0; i < card.size(); i++) {
+ Contact c = card.get(i);
if (filter == null
|| c.toString(format).toLowerCase()
.contains(filter.toLowerCase())) {