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