diff --git a/source/org/jivesoftware/smackx/packet/VCard.java b/source/org/jivesoftware/smackx/packet/VCard.java index 4f1248859..5898130d8 100644 --- a/source/org/jivesoftware/smackx/packet/VCard.java +++ b/source/org/jivesoftware/smackx/packet/VCard.java @@ -124,13 +124,35 @@ public class VCard extends IQ { /** * Set generic VCard field. * - * @param field value of field. Possible values: NICKNAME, PHOTO, BDAY, JABBERID, MAILER, TZ, + * @param field value of field. Possible values: FN, NICKNAME, PHOTO, BDAY, JABBERID, MAILER, TZ, * GEO, TITLE, ROLE, LOGO, NOTE, PRODID, REV, SORT-STRING, SOUND, UID, URL, DESC. */ public String getField(String field) { + if ("FN".equals(field)) { + return buildFullName(); + } return (String) otherSimpleFields.get(field); } + private String buildFullName() { + if (otherSimpleFields.containsKey("FN")) { + return otherSimpleFields.get("FN").toString().trim(); + } + else { + StringBuffer sb = new StringBuffer(); + if (firstName != null) { + sb.append(firstName).append(' '); + } + if (middleName != null) { + sb.append(middleName).append(' '); + } + if (lastName != null) { + sb.append(lastName); + } + return sb.toString().trim(); + } + } + /** * Set generic VCard field. * @@ -162,6 +184,13 @@ public class VCard extends IQ { return middleName; } + /** + * Returns the full name of the user, associated with this VCard. + */ + public String getFullName() { + return getField("FN"); + } + public void setMiddleName(String middleName) { this.middleName = middleName; } @@ -540,7 +569,7 @@ public class VCard extends IQ { } private boolean hasNameField() { - return firstName != null || lastName != null || middleName != null; + return firstName != null || lastName != null || middleName != null || otherSimpleFields.containsKey("FN"); } private boolean hasOrganizationFields() { @@ -638,7 +667,7 @@ public class VCard extends IQ { private void buildActualContent() { if (hasNameField()) { - appendFN(); + appendTag("FN", getFullName()); appendN(); } @@ -706,7 +735,9 @@ public class VCard extends IQ { Iterator it = otherSimpleFields.entrySet().iterator(); while (it.hasNext()) { Map.Entry entry = (Map.Entry) it.next(); - appendTag(entry.getKey().toString(), (String) entry.getValue()); + String tag = entry.getKey().toString(); + if ("FN".equals(tag)) continue; + appendTag(tag, (String) entry.getValue()); } } @@ -721,28 +752,6 @@ public class VCard extends IQ { } } - private void appendField(String tag) { - String value = (String) otherSimpleFields.get(tag); - appendTag(tag, value); - } - - private void appendFN() { - final ContentBuilder contentBuilder = new ContentBuilder() { - public void addTagContent() { - if (firstName != null) { - sb.append(firstName + ' '); - } - if (middleName != null) { - sb.append(middleName + ' '); - } - if (lastName != null) { - sb.append(lastName); - } - } - }; - appendTag("FN", true, contentBuilder); - } - private void appendN() { appendTag("N", true, new ContentBuilder() { public void addTagContent() { diff --git a/source/org/jivesoftware/smackx/provider/VCardProvider.java b/source/org/jivesoftware/smackx/provider/VCardProvider.java index 3caf730db..1596edfd6 100644 --- a/source/org/jivesoftware/smackx/provider/VCardProvider.java +++ b/source/org/jivesoftware/smackx/provider/VCardProvider.java @@ -31,6 +31,8 @@ import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import java.io.ByteArrayInputStream; import java.io.IOException; +import java.util.List; +import java.util.ArrayList; /** * Created by IntelliJ IDEA. @@ -52,10 +54,10 @@ public class VCardProvider implements IQProvider { sb.append(parser.getText()); break; case XmlPullParser.START_TAG: - sb.append('<' + parser.getName() + '>'); + sb.append('<').append(parser.getName()).append('>'); break; case XmlPullParser.END_TAG: - sb.append("'); + sb.append("'); break; default: } @@ -71,6 +73,10 @@ public class VCardProvider implements IQProvider { } String xmlText = sb.toString(); + return _createVCardFromXml(xmlText); + } + + public static VCard _createVCardFromXml(String xmlText) { VCard vCard = new VCard(); try { DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); @@ -85,7 +91,7 @@ public class VCardProvider implements IQProvider { return vCard; } - private class VCardReader { + private static class VCardReader { private final VCard vCard; private final Document document; @@ -106,58 +112,88 @@ public class VCardProvider implements IQProvider { vCard.setOrganizationUnit(getTagContents("ORGUNIT")); setupSimpleFields(); - setupPhones("WORK", true); - setupPhones("HOME", false); - setupAddress("WORK", true); - setupAddress("HOME", false); + setupPhones(); + setupAddresses(); } private void setupEmails() { NodeList nodes = document.getElementsByTagName("USERID"); + if (nodes == null) return; for (int i = 0; i < nodes.getLength(); i++) { Element element = (Element) nodes.item(i); - if ("WORK".equals(element.getParentNode().getFirstChild().getNodeName())) { - vCard.setEmailWork(getTextContent(element)); - } else { + if ("HOME".equals(element.getParentNode().getFirstChild().getNodeName())) { vCard.setEmailHome(getTextContent(element)); + } else { + vCard.setEmailWork(getTextContent(element)); } } } - private void setupPhones(String type, boolean work) { + private void setupPhones() { NodeList allPhones = document.getElementsByTagName("TEL"); + if (allPhones == null) return; for (int i = 0; i < allPhones.getLength(); i++) { - Element node = (Element) allPhones.item(i); - if (type.equals(node.getChildNodes().item(1).getNodeName())) { - String code = node.getFirstChild().getNodeName(); - String value = getTextContent(node.getChildNodes().item(2)); - if (work) { - vCard.setPhoneWork(code, value); + NodeList nodes = allPhones.item(i).getChildNodes(); + String type = null; + String code = null; + String value = null; + for (int j = 0; j < nodes.getLength(); j++) { + Node node = nodes.item(j); + if (node.getNodeType() != Node.ELEMENT_NODE) continue; + String nodeName = node.getNodeName(); + if ("NUMBER".equals(nodeName)) { + value = getTextContent(node); + } + else if (isWorkHome(nodeName)) { + type = nodeName; } else { + code = nodeName; + } + } + if (code == null || value == null) continue; + if ("HOME".equals(type)) { vCard.setPhoneHome(code, value); } + else { // By default, setup work phone + vCard.setPhoneWork(code, value); } } } - private void setupAddress(String type, boolean work) { + private boolean isWorkHome(String nodeName) { + return "HOME".equals(nodeName) || "WORK".equals(nodeName); + } + + private void setupAddresses() { NodeList allAddresses = document.getElementsByTagName("ADR"); + if (allAddresses == null) return; for (int i = 0; i < allAddresses.getLength(); i++) { - Element node = (Element) allAddresses.item(i); - NodeList childNodes = node.getChildNodes(); - if (type.equals(childNodes.item(0).getNodeName())) { - for (int j = 1; j < childNodes.getLength(); j++) { - Node item = childNodes.item(j); - if (item instanceof Element) { - if (work) { - vCard.setAddressFieldWork(item.getNodeName(), getTextContent(item)); + Element addressNode = (Element) allAddresses.item(i); + + String type = null; + List code = new ArrayList(); + List value = new ArrayList(); + NodeList childNodes = addressNode.getChildNodes(); + for(int j = 0; j < childNodes.getLength(); j++) { + Node node = childNodes.item(j); + if (node.getNodeType() != Node.ELEMENT_NODE) continue; + String nodeName = node.getNodeName(); + if (isWorkHome(nodeName)) { + type = nodeName; } else { - vCard.setAddressFieldHome(item.getNodeName(), getTextContent(item)); + code.add(nodeName); + value.add(getTextContent(node)); } } + for (int j = 0; j < value.size(); j++) { + if ("HOME".equals(type)) { + vCard.setAddressFieldHome((String) code.get(j), (String) value.get(j)); + } + else { // By default, setup work address + vCard.setAddressFieldWork((String) code.get(j), (String) value.get(j)); } } } @@ -165,7 +201,7 @@ public class VCardProvider implements IQProvider { private String getTagContents(String tag) { NodeList nodes = document.getElementsByTagName(tag); - if (nodes.getLength() == 1) { + if (nodes != null && nodes.getLength() == 1) { return getTextContent(nodes.item(0)); } return null; @@ -177,13 +213,13 @@ public class VCardProvider implements IQProvider { Node node = childNodes.item(i); if (node instanceof Element) { Element element = (Element) node; - if ("FN".equals(element.getNodeName())) continue; + String field = element.getNodeName(); if (element.getChildNodes().getLength() == 0) { - vCard.setField(element.getNodeName(), ""); + vCard.setField(field, ""); } else if (element.getChildNodes().getLength() == 1 && element.getChildNodes().item(0) instanceof Text) { - vCard.setField(element.getNodeName(), getTextContent(element)); + vCard.setField(field, getTextContent(element)); } } } diff --git a/test/org/jivesoftware/smackx/VCardTest.java b/test/org/jivesoftware/smackx/VCardTest.java index 30a6e3a65..7bdffbc7f 100644 --- a/test/org/jivesoftware/smackx/VCardTest.java +++ b/test/org/jivesoftware/smackx/VCardTest.java @@ -1,8 +1,9 @@ package org.jivesoftware.smackx; -import org.jivesoftware.smack.test.SmackTestCase; import org.jivesoftware.smack.XMPPException; +import org.jivesoftware.smack.test.SmackTestCase; import org.jivesoftware.smackx.packet.VCard; +import org.jivesoftware.smackx.provider.VCardProvider; /** * Created by IntelliJ IDEA. @@ -23,13 +24,18 @@ public class VCardTest extends SmackTestCase { origVCard.setFirstName("kir"); origVCard.setLastName("max"); origVCard.setEmailHome("foo@fee.bar"); + origVCard.setEmailWork("foo@fee.www.bar"); + origVCard.setJabberId("jabber@id.org"); origVCard.setOrganization("Jetbrains, s.r.o"); origVCard.setNickName("KIR"); origVCard.setField("TITLE", "Mr"); origVCard.setAddressFieldHome("STREET", "Some street"); + origVCard.setAddressFieldWork("STREET", "Some street work"); + origVCard.setPhoneWork("FAX", "3443233"); + origVCard.setPhoneHome("VOICE", "3443233"); origVCard.save(getConnection(0)); @@ -41,7 +47,7 @@ public class VCardTest extends SmackTestCase { fail(e.getMessage()); } - assertEquals("Should load own VCard successfully", origVCard, loaded); + assertEquals("Should load own VCard successfully", origVCard.toString(), loaded.toString()); loaded = new VCard(); try { @@ -51,7 +57,41 @@ public class VCardTest extends SmackTestCase { fail(e.getMessage()); } - assertEquals("Should load another user's VCard successfully", origVCard, loaded); + assertEquals("Should load another user's VCard successfully", origVCard.toString(), loaded.toString()); + } + + public void testNoWorkHomeSpecifier_EMAIL() throws Throwable { + VCard card = VCardProvider._createVCardFromXml("foo@fee.www.bar"); + assertEquals("foo@fee.www.bar", card.getEmailWork()); + } + + public void testNoWorkHomeSpecifier_TEL() throws Throwable { + VCard card = VCardProvider._createVCardFromXml("3443233"); + assertEquals("3443233", card.getPhoneWork("FAX")); + } + + public void testNoWorkHomeSpecifier_ADDR() throws Throwable { + VCard card = VCardProvider._createVCardFromXml("Some streetddss"); + assertEquals("Some street", card.getAddressFieldWork("STREET")); + assertEquals("ddss", card.getAddressFieldWork("FF")); + } + + public void testFN() throws Throwable { + VCard card = VCardProvider._createVCardFromXml("kir max"); + assertEquals("kir max", card.getField("FN")); + assertEquals("kir max", card.getFullName()); + } + + public void testFullName() throws Throwable { + VCard card = new VCard(); + card.setFirstName("kir"); + assertEquals("kir", card.getFullName()); + + card.setLastName("maximov"); + assertEquals("kir maximov", card.getFullName()); + + card.setField("FN", "some name"); + assertEquals("some name", card.getFullName()); } protected int getMaxConnections() {