diff options
Diffstat (limited to 'src/org/jivesoftware/smackx/provider/VCardProvider.java')
-rw-r--r-- | src/org/jivesoftware/smackx/provider/VCardProvider.java | 293 |
1 files changed, 293 insertions, 0 deletions
diff --git a/src/org/jivesoftware/smackx/provider/VCardProvider.java b/src/org/jivesoftware/smackx/provider/VCardProvider.java new file mode 100644 index 0000000..8fa0421 --- /dev/null +++ b/src/org/jivesoftware/smackx/provider/VCardProvider.java @@ -0,0 +1,293 @@ +/** + * $RCSfile$ + * $Revision$ + * $Date$ + * + * Copyright 2003-2007 Jive Software. + * + * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jivesoftware.smackx.provider; + +import org.jivesoftware.smack.packet.IQ; +import org.jivesoftware.smack.provider.IQProvider; +import org.jivesoftware.smack.util.StringUtils; +import org.jivesoftware.smackx.packet.VCard; +import org.w3c.dom.*; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * vCard provider. + * + * @author Gaston Dombiak + * @author Derek DeMoro + */ +public class VCardProvider implements IQProvider { + + private static final String PREFERRED_ENCODING = "UTF-8"; + + public IQ parseIQ(XmlPullParser parser) throws Exception { + final StringBuilder sb = new StringBuilder(); + try { + int event = parser.getEventType(); + // get the content + while (true) { + switch (event) { + case XmlPullParser.TEXT: + // We must re-escape the xml so that the DOM won't throw an exception + sb.append(StringUtils.escapeForXML(parser.getText())); + break; + case XmlPullParser.START_TAG: + sb.append('<').append(parser.getName()).append('>'); + break; + case XmlPullParser.END_TAG: + sb.append("</").append(parser.getName()).append('>'); + break; + default: + } + + if (event == XmlPullParser.END_TAG && "vCard".equals(parser.getName())) break; + + event = parser.next(); + } + } + catch (XmlPullParserException e) { + e.printStackTrace(); + } + catch (IOException e) { + e.printStackTrace(); + } + + String xmlText = sb.toString(); + return createVCardFromXML(xmlText); + } + + /** + * Builds a users vCard from xml file. + * + * @param xml the xml representing a users vCard. + * @return the VCard. + * @throws Exception if an exception occurs. + */ + public static VCard createVCardFromXML(String xml) throws Exception { + VCard vCard = new VCard(); + + DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); + Document document = documentBuilder.parse( + new ByteArrayInputStream(xml.getBytes(PREFERRED_ENCODING))); + + new VCardReader(vCard, document).initializeFields(); + return vCard; + } + + private static class VCardReader { + + private final VCard vCard; + private final Document document; + + VCardReader(VCard vCard, Document document) { + this.vCard = vCard; + this.document = document; + } + + public void initializeFields() { + vCard.setFirstName(getTagContents("GIVEN")); + vCard.setLastName(getTagContents("FAMILY")); + vCard.setMiddleName(getTagContents("MIDDLE")); + setupPhoto(); + + setupEmails(); + + vCard.setOrganization(getTagContents("ORGNAME")); + vCard.setOrganizationUnit(getTagContents("ORGUNIT")); + + setupSimpleFields(); + + setupPhones(); + setupAddresses(); + } + + private void setupPhoto() { + String binval = null; + String mimetype = null; + + NodeList photo = document.getElementsByTagName("PHOTO"); + if (photo.getLength() != 1) + return; + + Node photoNode = photo.item(0); + NodeList childNodes = photoNode.getChildNodes(); + + int childNodeCount = childNodes.getLength(); + List<Node> nodes = new ArrayList<Node>(childNodeCount); + for (int i = 0; i < childNodeCount; i++) + nodes.add(childNodes.item(i)); + + String name = null; + String value = null; + for (Node n : nodes) { + name = n.getNodeName(); + value = n.getTextContent(); + if (name.equals("BINVAL")) { + binval = value; + } + else if (name.equals("TYPE")) { + mimetype = value; + } + } + + if (binval == null || mimetype == null) + return; + + vCard.setAvatar(binval, mimetype); + } + + 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 { + vCard.setEmailHome(getTextContent(element)); + } + } + } + + private void setupPhones() { + NodeList allPhones = document.getElementsByTagName("TEL"); + if (allPhones == null) return; + for (int i = 0; i < allPhones.getLength(); i++) { + 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 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 addressNode = (Element) allAddresses.item(i); + + String type = null; + List<String> code = new ArrayList<String>(); + List<String> value = new ArrayList<String>(); + 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 { + 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)); + } + } + } + } + + private String getTagContents(String tag) { + NodeList nodes = document.getElementsByTagName(tag); + if (nodes != null && nodes.getLength() == 1) { + return getTextContent(nodes.item(0)); + } + return null; + } + + private void setupSimpleFields() { + NodeList childNodes = document.getDocumentElement().getChildNodes(); + for (int i = 0; i < childNodes.getLength(); i++) { + Node node = childNodes.item(i); + if (node instanceof Element) { + Element element = (Element) node; + + String field = element.getNodeName(); + if (element.getChildNodes().getLength() == 0) { + vCard.setField(field, ""); + } + else if (element.getChildNodes().getLength() == 1 && + element.getChildNodes().item(0) instanceof Text) { + vCard.setField(field, getTextContent(element)); + } + } + } + } + + private String getTextContent(Node node) { + StringBuilder result = new StringBuilder(); + appendText(result, node); + return result.toString(); + } + + private void appendText(StringBuilder result, Node node) { + NodeList childNodes = node.getChildNodes(); + for (int i = 0; i < childNodes.getLength(); i++) { + Node nd = childNodes.item(i); + String nodeValue = nd.getNodeValue(); + if (nodeValue != null) { + result.append(nodeValue); + } + appendText(result, nd); + } + } + } +} |