blob: 8fa04211d1bb1ec57a854a647dd02491cede0d81 [file] [log] [blame]
Shuyi Chend7955ce2013-05-22 14:51:55 -07001/**
2 * $RCSfile$
3 * $Revision$
4 * $Date$
5 *
6 * Copyright 2003-2007 Jive Software.
7 *
8 * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20
21package org.jivesoftware.smackx.provider;
22
23import org.jivesoftware.smack.packet.IQ;
24import org.jivesoftware.smack.provider.IQProvider;
25import org.jivesoftware.smack.util.StringUtils;
26import org.jivesoftware.smackx.packet.VCard;
27import org.w3c.dom.*;
28import org.xmlpull.v1.XmlPullParser;
29import org.xmlpull.v1.XmlPullParserException;
30
31import javax.xml.parsers.DocumentBuilder;
32import javax.xml.parsers.DocumentBuilderFactory;
33import java.io.ByteArrayInputStream;
34import java.io.IOException;
35import java.util.ArrayList;
36import java.util.List;
37
38/**
39 * vCard provider.
40 *
41 * @author Gaston Dombiak
42 * @author Derek DeMoro
43 */
44public class VCardProvider implements IQProvider {
45
46 private static final String PREFERRED_ENCODING = "UTF-8";
47
48 public IQ parseIQ(XmlPullParser parser) throws Exception {
49 final StringBuilder sb = new StringBuilder();
50 try {
51 int event = parser.getEventType();
52 // get the content
53 while (true) {
54 switch (event) {
55 case XmlPullParser.TEXT:
56 // We must re-escape the xml so that the DOM won't throw an exception
57 sb.append(StringUtils.escapeForXML(parser.getText()));
58 break;
59 case XmlPullParser.START_TAG:
60 sb.append('<').append(parser.getName()).append('>');
61 break;
62 case XmlPullParser.END_TAG:
63 sb.append("</").append(parser.getName()).append('>');
64 break;
65 default:
66 }
67
68 if (event == XmlPullParser.END_TAG && "vCard".equals(parser.getName())) break;
69
70 event = parser.next();
71 }
72 }
73 catch (XmlPullParserException e) {
74 e.printStackTrace();
75 }
76 catch (IOException e) {
77 e.printStackTrace();
78 }
79
80 String xmlText = sb.toString();
81 return createVCardFromXML(xmlText);
82 }
83
84 /**
85 * Builds a users vCard from xml file.
86 *
87 * @param xml the xml representing a users vCard.
88 * @return the VCard.
89 * @throws Exception if an exception occurs.
90 */
91 public static VCard createVCardFromXML(String xml) throws Exception {
92 VCard vCard = new VCard();
93
94 DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
95 DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
96 Document document = documentBuilder.parse(
97 new ByteArrayInputStream(xml.getBytes(PREFERRED_ENCODING)));
98
99 new VCardReader(vCard, document).initializeFields();
100 return vCard;
101 }
102
103 private static class VCardReader {
104
105 private final VCard vCard;
106 private final Document document;
107
108 VCardReader(VCard vCard, Document document) {
109 this.vCard = vCard;
110 this.document = document;
111 }
112
113 public void initializeFields() {
114 vCard.setFirstName(getTagContents("GIVEN"));
115 vCard.setLastName(getTagContents("FAMILY"));
116 vCard.setMiddleName(getTagContents("MIDDLE"));
117 setupPhoto();
118
119 setupEmails();
120
121 vCard.setOrganization(getTagContents("ORGNAME"));
122 vCard.setOrganizationUnit(getTagContents("ORGUNIT"));
123
124 setupSimpleFields();
125
126 setupPhones();
127 setupAddresses();
128 }
129
130 private void setupPhoto() {
131 String binval = null;
132 String mimetype = null;
133
134 NodeList photo = document.getElementsByTagName("PHOTO");
135 if (photo.getLength() != 1)
136 return;
137
138 Node photoNode = photo.item(0);
139 NodeList childNodes = photoNode.getChildNodes();
140
141 int childNodeCount = childNodes.getLength();
142 List<Node> nodes = new ArrayList<Node>(childNodeCount);
143 for (int i = 0; i < childNodeCount; i++)
144 nodes.add(childNodes.item(i));
145
146 String name = null;
147 String value = null;
148 for (Node n : nodes) {
149 name = n.getNodeName();
150 value = n.getTextContent();
151 if (name.equals("BINVAL")) {
152 binval = value;
153 }
154 else if (name.equals("TYPE")) {
155 mimetype = value;
156 }
157 }
158
159 if (binval == null || mimetype == null)
160 return;
161
162 vCard.setAvatar(binval, mimetype);
163 }
164
165 private void setupEmails() {
166 NodeList nodes = document.getElementsByTagName("USERID");
167 if (nodes == null) return;
168 for (int i = 0; i < nodes.getLength(); i++) {
169 Element element = (Element) nodes.item(i);
170 if ("WORK".equals(element.getParentNode().getFirstChild().getNodeName())) {
171 vCard.setEmailWork(getTextContent(element));
172 }
173 else {
174 vCard.setEmailHome(getTextContent(element));
175 }
176 }
177 }
178
179 private void setupPhones() {
180 NodeList allPhones = document.getElementsByTagName("TEL");
181 if (allPhones == null) return;
182 for (int i = 0; i < allPhones.getLength(); i++) {
183 NodeList nodes = allPhones.item(i).getChildNodes();
184 String type = null;
185 String code = null;
186 String value = null;
187 for (int j = 0; j < nodes.getLength(); j++) {
188 Node node = nodes.item(j);
189 if (node.getNodeType() != Node.ELEMENT_NODE) continue;
190 String nodeName = node.getNodeName();
191 if ("NUMBER".equals(nodeName)) {
192 value = getTextContent(node);
193 }
194 else if (isWorkHome(nodeName)) {
195 type = nodeName;
196 }
197 else {
198 code = nodeName;
199 }
200 }
201 if (code == null || value == null) continue;
202 if ("HOME".equals(type)) {
203 vCard.setPhoneHome(code, value);
204 }
205 else { // By default, setup work phone
206 vCard.setPhoneWork(code, value);
207 }
208 }
209 }
210
211 private boolean isWorkHome(String nodeName) {
212 return "HOME".equals(nodeName) || "WORK".equals(nodeName);
213 }
214
215 private void setupAddresses() {
216 NodeList allAddresses = document.getElementsByTagName("ADR");
217 if (allAddresses == null) return;
218 for (int i = 0; i < allAddresses.getLength(); i++) {
219 Element addressNode = (Element) allAddresses.item(i);
220
221 String type = null;
222 List<String> code = new ArrayList<String>();
223 List<String> value = new ArrayList<String>();
224 NodeList childNodes = addressNode.getChildNodes();
225 for (int j = 0; j < childNodes.getLength(); j++) {
226 Node node = childNodes.item(j);
227 if (node.getNodeType() != Node.ELEMENT_NODE) continue;
228 String nodeName = node.getNodeName();
229 if (isWorkHome(nodeName)) {
230 type = nodeName;
231 }
232 else {
233 code.add(nodeName);
234 value.add(getTextContent(node));
235 }
236 }
237 for (int j = 0; j < value.size(); j++) {
238 if ("HOME".equals(type)) {
239 vCard.setAddressFieldHome((String) code.get(j), (String) value.get(j));
240 }
241 else { // By default, setup work address
242 vCard.setAddressFieldWork((String) code.get(j), (String) value.get(j));
243 }
244 }
245 }
246 }
247
248 private String getTagContents(String tag) {
249 NodeList nodes = document.getElementsByTagName(tag);
250 if (nodes != null && nodes.getLength() == 1) {
251 return getTextContent(nodes.item(0));
252 }
253 return null;
254 }
255
256 private void setupSimpleFields() {
257 NodeList childNodes = document.getDocumentElement().getChildNodes();
258 for (int i = 0; i < childNodes.getLength(); i++) {
259 Node node = childNodes.item(i);
260 if (node instanceof Element) {
261 Element element = (Element) node;
262
263 String field = element.getNodeName();
264 if (element.getChildNodes().getLength() == 0) {
265 vCard.setField(field, "");
266 }
267 else if (element.getChildNodes().getLength() == 1 &&
268 element.getChildNodes().item(0) instanceof Text) {
269 vCard.setField(field, getTextContent(element));
270 }
271 }
272 }
273 }
274
275 private String getTextContent(Node node) {
276 StringBuilder result = new StringBuilder();
277 appendText(result, node);
278 return result.toString();
279 }
280
281 private void appendText(StringBuilder result, Node node) {
282 NodeList childNodes = node.getChildNodes();
283 for (int i = 0; i < childNodes.getLength(); i++) {
284 Node nd = childNodes.item(i);
285 String nodeValue = nd.getNodeValue();
286 if (nodeValue != null) {
287 result.append(nodeValue);
288 }
289 appendText(result, nd);
290 }
291 }
292 }
293}