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 java.io.IOException; 020 021import org.jivesoftware.smack.packet.XmlEnvironment; 022import org.jivesoftware.smack.provider.IQProvider; 023import org.jivesoftware.smack.util.StringUtils; 024import org.jivesoftware.smack.xml.XmlPullParser; 025import org.jivesoftware.smack.xml.XmlPullParserException; 026 027import org.jivesoftware.smackx.vcardtemp.packet.VCard; 028 029/** 030 * vCard provider. 031 * 032 * @author Gaston Dombiak 033 * @author Derek DeMoro 034 * @author Chris Deering 035 */ 036public class VCardProvider extends IQProvider<VCard> { 037 038 // @formatter:off 039 private static final String[] ADR = new String[] { 040 "POSTAL", 041 "PARCEL", 042 "DOM", 043 "INTL", 044 "PREF", 045 "POBOX", 046 "EXTADR", 047 "STREET", 048 "LOCALITY", 049 "REGION", 050 "PCODE", 051 "CTRY", 052 "FF", 053 }; 054 055 private static final String[] TEL = new String[] { 056 "VOICE", 057 "FAX", 058 "PAGER", 059 "MSG", 060 "CELL", 061 "VIDEO", 062 "BBS", 063 "MODEM", 064 "ISDN", 065 "PCS", 066 "PREF", 067 }; 068 // @formatter:on 069 070 @Override 071 public VCard parse(XmlPullParser parser, int initialDepth, XmlEnvironment xmlEnvironment) throws XmlPullParserException, IOException { 072 VCard vCard = new VCard(); 073 String name = null; 074 075 outerloop: while (true) { 076 XmlPullParser.Event eventType = parser.next(); 077 switch (eventType) { 078 case START_ELEMENT: 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 TEXT_CHARACTERS: 110 if (initialDepth + 1 == parser.getDepth()) { 111 String text = parser.getText(); 112 vCard.setField(name, text); 113 } 114 break; 115 case END_ELEMENT: 116 if (parser.getDepth() == initialDepth) { 117 break outerloop; 118 } 119 break; 120 default: 121 break; 122 } 123 } 124 125 return vCard; 126 } 127 128 private static void parseAddress(XmlPullParser parser, VCard vCard) throws XmlPullParserException, IOException { 129 final int initialDepth = parser.getDepth(); 130 boolean isWork = true; 131 outerloop: while (true) { 132 XmlPullParser.Event eventType = parser.next(); 133 switch (eventType) { 134 case START_ELEMENT: 135 String name = parser.getName(); 136 if ("HOME".equals(name)) { 137 isWork = false; 138 } 139 else { 140 for (String adr : ADR) { 141 if (adr.equals(name)) { 142 if (isWork) { 143 vCard.setAddressFieldWork(name, parser.nextText()); 144 } 145 else { 146 vCard.setAddressFieldHome(name, parser.nextText()); 147 } 148 } 149 } 150 } 151 break; 152 case END_ELEMENT: 153 if (parser.getDepth() == initialDepth) { 154 break outerloop; 155 } 156 break; 157 default: 158 break; 159 } 160 } 161 } 162 163 private static void parseTel(XmlPullParser parser, VCard vCard) throws XmlPullParserException, IOException { 164 final int initialDepth = parser.getDepth(); 165 boolean isWork = true; 166 String telLabel = null; 167 168 outerloop: while (true) { 169 XmlPullParser.Event eventType = parser.next(); 170 switch (eventType) { 171 case START_ELEMENT: 172 String name = parser.getName(); 173 if ("HOME".equals(name)) { 174 isWork = false; 175 } 176 else { 177 if ("NUMBER".equals(name)) { 178 if (StringUtils.isNullOrEmpty(telLabel)) { 179 // RFC 2426 ยง 3.3.1: 180 // "The default type is 'voice'" 181 telLabel = "VOICE"; 182 } 183 if (isWork) { 184 vCard.setPhoneWork(telLabel, parser.nextText()); 185 } 186 else { 187 vCard.setPhoneHome(telLabel, parser.nextText()); 188 } 189 } 190 else { 191 for (String tel : TEL) { 192 if (tel.equals(name)) { 193 telLabel = name; 194 } 195 } 196 } 197 } 198 break; 199 case END_ELEMENT: 200 if (parser.getDepth() == initialDepth) { 201 break outerloop; 202 } 203 break; 204 default: 205 break; 206 } 207 } 208 } 209 210 private static void parseOrg(XmlPullParser parser, VCard vCard) throws XmlPullParserException, IOException { 211 final int initialDepth = parser.getDepth(); 212 213 outerloop: while (true) { 214 XmlPullParser.Event eventType = parser.next(); 215 switch (eventType) { 216 case START_ELEMENT: 217 String name = parser.getName(); 218 switch (name) { 219 case "ORGNAME": 220 vCard.setOrganization(parser.nextText()); 221 break; 222 case "ORGUNIT": 223 vCard.setOrganizationUnit(parser.nextText()); 224 break; 225 default: 226 break; 227 } 228 break; 229 case END_ELEMENT: 230 if (parser.getDepth() == initialDepth) { 231 break outerloop; 232 } 233 break; 234 default: 235 break; 236 } 237 } 238 } 239 240 private static void parseEmail(XmlPullParser parser, VCard vCard) throws XmlPullParserException, IOException { 241 final int initialDepth = parser.getDepth(); 242 boolean isWork = false; 243 244 outerloop: while (true) { 245 XmlPullParser.Event eventType = parser.next(); 246 switch (eventType) { 247 case START_ELEMENT: 248 String name = parser.getName(); 249 switch (name) { 250 case "WORK": 251 isWork = true; 252 break; 253 case "USERID": 254 if (isWork) { 255 vCard.setEmailWork(parser.nextText()); 256 } 257 else { 258 vCard.setEmailHome(parser.nextText()); 259 } 260 break; 261 default: 262 break; 263 } 264 break; 265 case END_ELEMENT: 266 if (parser.getDepth() == initialDepth) { 267 break outerloop; 268 } 269 break; 270 default: 271 break; 272 } 273 } 274 } 275 276 private static void parseName(XmlPullParser parser, VCard vCard) throws XmlPullParserException, IOException { 277 final int initialDepth = parser.getDepth(); 278 279 outerloop: while (true) { 280 XmlPullParser.Event eventType = parser.next(); 281 switch (eventType) { 282 case START_ELEMENT: 283 String name = parser.getName(); 284 switch (name) { 285 case "FAMILY": 286 vCard.setLastName(parser.nextText()); 287 break; 288 case "GIVEN": 289 vCard.setFirstName(parser.nextText()); 290 break; 291 case "MIDDLE": 292 vCard.setMiddleName(parser.nextText()); 293 break; 294 case "PREFIX": 295 vCard.setPrefix(parser.nextText()); 296 break; 297 case "SUFFIX": 298 vCard.setSuffix(parser.nextText()); 299 break; 300 default: 301 break; 302 } 303 break; 304 case END_ELEMENT: 305 if (parser.getDepth() == initialDepth) { 306 break outerloop; 307 } 308 break; 309 default: 310 break; 311 312 } 313 } 314 } 315 316 private static void parsePhoto(XmlPullParser parser, VCard vCard) throws XmlPullParserException, IOException { 317 final int initialDepth = parser.getDepth(); 318 String binval = null; 319 String mimetype = null; 320 321 outerloop: while (true) { 322 XmlPullParser.Event eventType = parser.next(); 323 switch (eventType) { 324 case START_ELEMENT: 325 String name = parser.getName(); 326 switch (name) { 327 case "BINVAL": 328 binval = parser.nextText(); 329 break; 330 case "TYPE": 331 mimetype = parser.nextText(); 332 break; 333 default: 334 break; 335 } 336 break; 337 case END_ELEMENT: 338 if (parser.getDepth() == initialDepth) { 339 break outerloop; 340 } 341 break; 342 default: 343 break; 344 } 345 } 346 347 if (binval == null || mimetype == null) { 348 return; 349 } 350 351 vCard.setAvatar(binval, mimetype); 352 } 353}