1/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package com.android.messaging.datamodel.media;
17
18import android.accounts.Account;
19import com.android.vcard.VCardConfig;
20import com.android.vcard.VCardInterpreter;
21import com.android.vcard.VCardProperty;
22
23import java.util.ArrayList;
24import java.util.List;
25
26public class CustomVCardEntryConstructor implements VCardInterpreter {
27
28    public interface EntryHandler {
29        /**
30         * Called when the parsing started.
31         */
32        public void onStart();
33
34        /**
35         * The method called when one vCard entry is created. Children come before their parent in
36         * nested vCard files.
37         *
38         * e.g.
39         * In the following vCard, the entry for "entry2" comes before one for "entry1".
40         * <code>
41         * BEGIN:VCARD
42         * N:entry1
43         * BEGIN:VCARD
44         * N:entry2
45         * END:VCARD
46         * END:VCARD
47         * </code>
48         */
49        public void onEntryCreated(final CustomVCardEntry entry);
50
51        /**
52         * Called when the parsing ended.
53         * Able to be use this method for showing performance log, etc.
54         */
55        public void onEnd();
56    }
57
58    /**
59     * Represents current stack of VCardEntry. Used to support nested vCard (vCard 2.1).
60     */
61    private final List<CustomVCardEntry> mEntryStack = new ArrayList<CustomVCardEntry>();
62    private CustomVCardEntry mCurrentEntry;
63
64    private final int mVCardType;
65    private final Account mAccount;
66
67    private final List<EntryHandler> mEntryHandlers = new ArrayList<EntryHandler>();
68
69    public CustomVCardEntryConstructor() {
70        this(VCardConfig.VCARD_TYPE_V21_GENERIC, null);
71    }
72
73    public CustomVCardEntryConstructor(final int vcardType) {
74        this(vcardType, null);
75    }
76
77    public CustomVCardEntryConstructor(final int vcardType, final Account account) {
78        mVCardType = vcardType;
79        mAccount = account;
80    }
81
82    public void addEntryHandler(EntryHandler entryHandler) {
83        mEntryHandlers.add(entryHandler);
84    }
85
86    @Override
87    public void onVCardStarted() {
88        for (EntryHandler entryHandler : mEntryHandlers) {
89            entryHandler.onStart();
90        }
91    }
92
93    @Override
94    public void onVCardEnded() {
95        for (EntryHandler entryHandler : mEntryHandlers) {
96            entryHandler.onEnd();
97        }
98    }
99
100    public void clear() {
101        mCurrentEntry = null;
102        mEntryStack.clear();
103    }
104
105    @Override
106    public void onEntryStarted() {
107        mCurrentEntry = new CustomVCardEntry(mVCardType, mAccount);
108        mEntryStack.add(mCurrentEntry);
109    }
110
111    @Override
112    public void onEntryEnded() {
113        mCurrentEntry.consolidateFields();
114        for (EntryHandler entryHandler : mEntryHandlers) {
115            entryHandler.onEntryCreated(mCurrentEntry);
116        }
117
118        final int size = mEntryStack.size();
119        if (size > 1) {
120            CustomVCardEntry parent = mEntryStack.get(size - 2);
121            parent.addChild(mCurrentEntry);
122            mCurrentEntry = parent;
123        } else {
124            mCurrentEntry = null;
125        }
126        mEntryStack.remove(size - 1);
127    }
128
129    @Override
130    public void onPropertyCreated(VCardProperty property) {
131        mCurrentEntry.addProperty(property);
132    }
133}