001/** 002 * 003 * Copyright 2003-2007 Jive Software. 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.jivesoftware.smackx.vcardtemp.provider; 018 019import org.jivesoftware.smack.SmackException; 020import org.jivesoftware.smack.provider.IQProvider; 021import org.jivesoftware.smack.util.StringUtils; 022import org.jivesoftware.smackx.vcardtemp.packet.VCard; 023import org.xmlpull.v1.XmlPullParser; 024import org.xmlpull.v1.XmlPullParserException; 025 026import java.io.IOException; 027 028/** 029 * vCard provider. 030 * 031 * @author Gaston Dombiak 032 * @author Derek DeMoro 033 * @author Chris Deering 034 */ 035public class VCardProvider extends IQProvider<VCard> { 036 037 // @formatter:off 038 private static final String[] ADR = new String[] { 039 "POSTAL", 040 "PARCEL", 041 "DOM", 042 "INTL", 043 "PREF", 044 "POBOX", 045 "EXTADR", 046 "STREET", 047 "LOCALITY", 048 "REGION", 049 "PCODE", 050 "CTRY", 051 "FF", 052 }; 053 054 private static final String[] TEL = new String[] { 055 "VOICE", 056 "FAX", 057 "PAGER", 058 "MSG", 059 "CELL", 060 "VIDEO", 061 "BBS", 062 "MODEM", 063 "ISDN", 064 "PCS", 065 "PREF", 066 }; 067 // @formatter:on 068 069 @Override 070 public VCard parse(XmlPullParser parser, int initialDepth) throws XmlPullParserException, IOException, 071 SmackException { 072 VCard vCard = new VCard(); 073 String name = null; 074 075 outerloop: while (true) { 076 int eventType = parser.next(); 077 switch (eventType) { 078 case XmlPullParser.START_TAG: 079 name = parser.getName(); 080 switch (name) { 081 case "N": 082 parseName(parser, vCard); 083 break; 084 case "ORG": 085 parseOrg(parser, vCard); 086 break; 087 case "TEL": 088 parseTel(parser, vCard); 089 break; 090 case "ADR": 091 parseAddress(parser, vCard); 092 break; 093 case "EMAIL": 094 parseEmail(parser, vCard); 095 break; 096 case "NICKNAME": 097 vCard.setNickName(parser.nextText()); 098 break; 099 case "JABBERID": 100 vCard.setJabberId(parser.nextText()); 101 break; 102 case "PHOTO": 103 parsePhoto(parser, vCard); 104 break; 105 default: 106 break; 107 } 108 break; 109 case XmlPullParser.TEXT: 110 if (initialDepth + 1 == parser.getDepth()) { 111 vCard.setField(name, parser.getText()); 112 } 113 break; 114 case XmlPullParser.END_TAG: 115 if (parser.getDepth() == initialDepth) { 116 break outerloop; 117 } 118 break; 119 default: 120 break; 121 } 122 } 123 124 return vCard; 125 } 126 127 private static void parseAddress(XmlPullParser parser, VCard vCard) throws XmlPullParserException, IOException { 128 final int initialDepth = parser.getDepth(); 129 boolean isWork = true; 130 outerloop: while (true) { 131 int eventType = parser.next(); 132 switch (eventType) { 133 case XmlPullParser.START_TAG: 134 String name = parser.getName(); 135 if ("HOME".equals(name)) { 136 isWork = false; 137 } 138 else { 139 for (String adr : ADR) { 140 if (adr.equals(name)) { 141 if (isWork) { 142 vCard.setAddressFieldWork(name, parser.nextText()); 143 } 144 else { 145 vCard.setAddressFieldHome(name, parser.nextText()); 146 } 147 } 148 } 149 } 150 break; 151 case XmlPullParser.END_TAG: 152 if (parser.getDepth() == initialDepth) { 153 break outerloop; 154 } 155 break; 156 default: 157 break; 158 } 159 } 160 } 161 162 private static void parseTel(XmlPullParser parser, VCard vCard) throws XmlPullParserException, IOException { 163 final int initialDepth = parser.getDepth(); 164 boolean isWork = true; 165 String telLabel = null; 166 167 outerloop: while (true) { 168 int eventType = parser.next(); 169 switch (eventType) { 170 case XmlPullParser.START_TAG: 171 String name = parser.getName(); 172 if ("HOME".equals(name)) { 173 isWork = false; 174 } 175 else { 176 if ("NUMBER".equals(name)) { 177 if (StringUtils.isNullOrEmpty(telLabel)) { 178 // RFC 2426 ยง 3.3.1: 179 // "The default type is 'voice'" 180 telLabel = "VOICE"; 181 } 182 if (isWork) { 183 vCard.setPhoneWork(telLabel, parser.nextText()); 184 } 185 else { 186 vCard.setPhoneHome(telLabel, parser.nextText()); 187 } 188 } 189 else { 190 for (String tel : TEL) { 191 if (tel.equals(name)) { 192 telLabel = name; 193 } 194 } 195 } 196 } 197 break; 198 case XmlPullParser.END_TAG: 199 if (parser.getDepth() == initialDepth) { 200 break outerloop; 201 } 202 break; 203 default: 204 break; 205 } 206 } 207 } 208 209 private static void parseOrg(XmlPullParser parser, VCard vCard) throws XmlPullParserException, IOException { 210 final int initialDepth = parser.getDepth(); 211 212 outerloop: while (true) { 213 int eventType = parser.next(); 214 switch (eventType) { 215 case XmlPullParser.START_TAG: 216 String name = parser.getName(); 217 switch (name) { 218 case "ORGNAME": 219 vCard.setOrganization(parser.nextText()); 220 break; 221 case "ORGUNIT": 222 vCard.setOrganizationUnit(parser.nextText()); 223 break; 224 default: 225 break; 226 } 227 break; 228 case XmlPullParser.END_TAG: 229 if (parser.getDepth() == initialDepth) { 230 break outerloop; 231 } 232 break; 233 default: 234 break; 235 } 236 } 237 } 238 239 private static void parseEmail(XmlPullParser parser, VCard vCard) throws XmlPullParserException, IOException { 240 final int initialDepth = parser.getDepth(); 241 boolean isWork = false; 242 243 outerloop: while (true) { 244 int eventType = parser.next(); 245 switch (eventType) { 246 case XmlPullParser.START_TAG: 247 String name = parser.getName(); 248 switch (name) { 249 case "WORK": 250 isWork = true; 251 break; 252 case "USERID": 253 if (isWork) { 254 vCard.setEmailWork(parser.nextText()); 255 } 256 else { 257 vCard.setEmailHome(parser.nextText()); 258 } 259 break; 260 default: 261 break; 262 } 263 break; 264 case XmlPullParser.END_TAG: 265 if (parser.getDepth() == initialDepth) { 266 break outerloop; 267 } 268 break; 269 default: 270 break; 271 } 272 } 273 } 274 275 private static void parseName(XmlPullParser parser, VCard vCard) throws XmlPullParserException, IOException { 276 final int initialDepth = parser.getDepth(); 277 278 outerloop: while (true) { 279 int eventType = parser.next(); 280 switch (eventType) { 281 case XmlPullParser.START_TAG: 282 String name = parser.getName(); 283 switch (name) { 284 case "FAMILY": 285 vCard.setLastName(parser.nextText()); 286 break; 287 case "GIVEN": 288 vCard.setFirstName(parser.nextText()); 289 break; 290 case "MIDDLE": 291 vCard.setMiddleName(parser.nextText()); 292 break; 293 case "PREFIX": 294 vCard.setPrefix(parser.nextText()); 295 break; 296 case "SUFFIX": 297 vCard.setSuffix(parser.nextText()); 298 break; 299 default: 300 break; 301 } 302 break; 303 case XmlPullParser.END_TAG: 304 if (parser.getDepth() == initialDepth) { 305 break outerloop; 306 } 307 break; 308 default: 309 break; 310 311 } 312 } 313 } 314 315 private static void parsePhoto(XmlPullParser parser, VCard vCard) throws XmlPullParserException, IOException { 316 final int initialDepth = parser.getDepth(); 317 String binval = null; 318 String mimetype = null; 319 320 outerloop: while (true) { 321 int eventType = parser.next(); 322 switch (eventType) { 323 case XmlPullParser.START_TAG: 324 String name = parser.getName(); 325 switch (name) { 326 case "BINVAL": 327 binval = parser.nextText(); 328 break; 329 case "TYPE": 330 mimetype = parser.nextText(); 331 break; 332 default: 333 break; 334 } 335 break; 336 case XmlPullParser.END_TAG: 337 if (parser.getDepth() == initialDepth) { 338 break outerloop; 339 } 340 break; 341 default: 342 break; 343 } 344 } 345 346 if (binval == null || mimetype == null) { 347 return; 348 } 349 350 vCard.setAvatar(binval, mimetype); 351 } 352}