import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import java.util.UUID;
import be.nikiroo.jvcard.parsers.Format;
import be.nikiroo.jvcard.parsers.Parser;
-import be.nikiroo.jvcard.tui.StringUtils;
+import be.nikiroo.jvcard.resources.StringUtils;
/**
* A contact is the information that represent a contact person or organisation.
}
/**
- * Return the preferred Data field with the given name, or NULL if none.
+ * Return the preferred Data field with the given name, the first one if
+ * none is preferred, or NULL if none at all.
*
* @param name
* the name to look for
- * @return the Data field, or NULL
+ *
+ * @return the {@link Data} field, or NULL
*/
public Data getPreferredData(String name) {
- Data first = null;
+ Data pref = null;
+ int ipref = Integer.MAX_VALUE;
for (Data data : getData(name)) {
- if (first == null)
- first = data;
- for (int index = 0; index < data.size(); index++) {
- TypeInfo type = data.get(index);
- if (type.getName().equals("TYPE")
- && type.getValue().equals("pref")) {
- return data;
- }
- }
+ if (pref == null)
+ pref = data;
+
+ if (data.getPreferred() < ipref)
+ pref = data;
}
- return first;
+ return pref;
}
/**
return found;
}
- /**
- * Return a {@link String} representation of this contact.
- *
- * @param format
- * the {@link Format} to use
- * @param startingBKey
- * the starting BKey or -1 for no BKeys
- * @return the {@link String} representation
- */
- public String toString(Format format, int startingBKey) {
- updateBKeys(false);
- return Parser.toString(this, format, startingBKey);
- }
-
/**
* Return a {@link String} representation of this contact formated
* accordingly to the given format.
*
+ * <p>
* The format is basically a list of field names separated by a pipe and
- * optionally parametrised. The parameters allows you to:
+ * optionally parametrised with the 'at' (@) symbol. The parameters allows
+ * you to:
* <ul>
* <li>@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>
+ * </p>
*
- * Example: "N@10|FN@20|NICK@+|PHOTO@x"
+ * <p>
+ * In case of lists or multiple-fields values, you can select a specific
+ * list or field with:
+ * <ul>
+ * <li>FIELD@(0): select the first value in a list</li>
+ * <li>FIELD@[1]: select the second field in a multiple-fields value</li>
+ * </ul>
+ * </p>
+ *
+ * <p>
+ * You can also add a fixed text if it starts with a simple-quote (').
+ * </p>
+ *
+ * <p>
+ * Example: "'Contact: |N@10|FN@20|NICK@+|PHOTO@x"
+ * </p>
*
* @param format
* the format to use
+ * @param separator
+ * the separator {@link String} to use between fields
*
* @return the {@link String} representation
*/
- public String toString(String format) {
- return toString(format, "|", null, -1, true, false);
+ public String toString(String format, String separator) {
+ return toString(format, separator, null, -1, true, false);
}
/**
* Return a {@link String} representation of this contact formated
* accordingly to the given format.
*
+ * <p>
* The format is basically a list of field names separated by a pipe and
* optionally parametrised. The parameters allows you to:
* <ul>
- * <li>@x: (the 'x' is the letter 'x') show only a present/not present info</li>
+ * <li>@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>
+ * </p>
*
- * Example: "N@10|FN@20|NICK@+|PHOTO@x"
+ * <p>
+ * In case of lists or multiple-fields values, you can select a specific
+ * list or field with:
+ * <ul>
+ * <li>FIELD@(0): select the first value in a list</li>
+ * <li>FIELD@[1]: select the second field in a multiple-fields value</li>
+ * </ul>
+ * </p>
+ *
+ * <p>
+ * You can also add a fixed text if it starts with a simple-quote (').
+ * </p>
+ *
+ * <p>
+ * Example: "'Contact: |N@10|FN@20|NICK@+|PHOTO@x"
+ * </p>
*
* @param format
* the format to use
* Return a {@link String} representation of this contact formated
* accordingly to the given format, part by part.
*
+ * <p>
* The format is basically a list of field names separated by a pipe and
* optionally parametrised. The parameters allows you to:
* <ul>
* <li>@n: limit the size to a fixed value 'n'</li>
* <li>@+: expand the size of this field as much as possible</li>
* </ul>
+ * </p>
+ *
+ * <p>
+ * In case of lists or multiple-fields values, you can select a specific
+ * list or field with:
+ * <ul>
+ * <li>FIELD@(0): select the first value in a list</li>
+ * <li>FIELD@[1]: select the second field in a multiple-fields value</li>
+ * </ul>
+ * </p>
*
- * Example: "N@10|FN@20|NICK@+|PHOTO@x"
+ * <p>
+ * You can also add a fixed text if it starts with a simple-quote (').
+ * </p>
+ *
+ * <p>
+ * Example: "'Contact: |N@10|FN@20|NICK@+|PHOTO@x"
+ * </p>
*
* @param format
* the format to use
* Return a {@link String} representation of this contact formated
* accordingly to the given format, part by part.
*
+ * <p>
* The format is basically a list of field names separated by a pipe and
* optionally parametrised. The parameters allows you to:
* <ul>
* <li>@n: limit the size to a fixed value 'n'</li>
* <li>@+: expand the size of this field as much as possible</li>
* </ul>
+ * </p>
+ *
+ * <p>
+ * In case of lists or multiple-fields values, you can select a specific
+ * list or field with:
+ * <ul>
+ * <li>FIELD@(0): select the first value in a list</li>
+ * <li>FIELD@[1]: select the second field in a multiple-fields value</li>
+ * </ul>
+ * </p>
*
- * Example: "N@10|FN@20|NICK@+|PHOTO@x"
+ * <p>
+ * You can also add a fixed text if it starts with a simple-quote (').
+ * </p>
+ *
+ * <p>
+ * Example: "'Contact: |N@10|FN@20|NICK@+|PHOTO@x"
+ * </p>
*
* @param format
* the format to use
int size = -1;
boolean binary = false;
boolean expand = false;
+ int fieldNum = -1;
+ int valueNum = -1;
- if (field.contains("@")) {
+ if (field.length() > 0 && field.charAt(0) != '\''
+ && field.contains("@")) {
String[] opts = field.split("@");
if (opts.length > 0)
field = opts[0];
} else if (opt.equals("+")) {
expand = true;
numOfFieldsToExpand++;
+ } else if (opt.length() > 0 && opt.charAt(0) == '(') {
+ try {
+ opt = opt.substring(1, opt.length() - 1);
+ valueNum = Integer.parseInt(opt);
+ } catch (Exception e) {
+ }
+ } else if (opt.length() > 0 && opt.charAt(0) == '[') {
+ try {
+ opt = opt.substring(1, opt.length() - 1);
+ fieldNum = Integer.parseInt(opt);
+ } catch (Exception e) {
+ }
} else {
try {
size = Integer.parseInt(opt);
- } catch (Exception e) {
+ } catch (NumberFormatException e) {
}
}
}
}
- String value = getPreferredDataValue(field);
+ String value = null;
+ if (field.length() > 0 && field.charAt(0) == '\'') {
+ value = field.substring(1);
+ } else if (valueNum >= 0) {
+ List<String> vv = getPreferredData(field).getValues();
+ if (valueNum < vv.size()) {
+ value = vv.get(valueNum);
+ }
+ } else if (fieldNum >= 0) {
+ List<String> ff = getPreferredData(field).getFields();
+ if (fieldNum < ff.size()) {
+ value = ff.get(fieldNum);
+ }
+ } else {
+ // we don't need the *data* in binary mode...
+ if (binary)
+ value = getData(field).size() > 0 ? "x" : null;
+ else
+ value = getPreferredDataValue(field);
+ }
+
if (value == null) {
value = "";
} else {
this.nextBKey = vc.nextBKey;
}
+ @Override
+ public String getId() {
+ return "" + getPreferredDataValue("UID");
+ }
+
+ @Override
+ public String getState() {
+ return getId();
+ }
+
/**
* Return a {@link String} representation of this contact, in vCard 2.1,
* without BKeys.
*/
@Override
public String toString() {
- return toString(Format.VCard21, -1);
+ return "[Contact: " + getPreferredDataValue("FN") + "]";
}
/**
boolean fn = false;
boolean n = false;
+ boolean uid = false;
if (content != null) {
for (Data data : content) {
if (data.getName().equals("N")) {
n = true;
} else if (data.getName().equals("FN")) {
fn = true;
+ } else if (data.getName().equals("UID")) {
+ uid = true;
}
if (!data.getName().equals("VERSION")) {
}
// required fields:
- if (!n) {
+ if (!n) // required since vCard 3.0, supported in 2.1
datas.add(new Data(null, "N", "", null));
- }
- if (!fn) {
+ if (!fn) // not required anymore but still supported in 4.0
datas.add(new Data(null, "FN", "", null));
- }
+ if (!uid) // supported by vCard, required by this program
+ datas.add(new Data(null, "UID", UUID.randomUUID().toString(), null));
return datas;
}