14199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa/*
24199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * Copyright (C) 2009 The Android Open Source Project
34199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa *
44199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * Licensed under the Apache License, Version 2.0 (the "License");
54199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * you may not use this file except in compliance with the License.
64199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * You may obtain a copy of the License at
74199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa *
84199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa *      http://www.apache.org/licenses/LICENSE-2.0
94199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa *
104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * Unless required by applicable law or agreed to in writing, software
114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * distributed under the License is distributed on an "AS IS" BASIS,
124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * See the License for the specific language governing permissions and
144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * limitations under the License.
154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */
16677ef21613a9d35053ec098444832ce4125a847eDaisuke Miyakawapackage com.android.vcard.tests.testutils;
174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
181de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawaimport com.android.vcard.VCardConfig;
191de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawaimport com.android.vcard.VCardInterpreter;
201de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawaimport com.android.vcard.VCardProperty;
211de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawaimport com.android.vcard.VCardUtils;
221de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.content.ContentValues;
244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.util.Base64;
254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.util.CharsetUtils;
264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.util.Log;
274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.io.UnsupportedEncodingException;
294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.nio.ByteBuffer;
304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.nio.charset.Charset;
314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.util.ArrayList;
321de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawaimport java.util.Collection;
334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.util.List;
341de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawaimport java.util.Map;
354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa/**
374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * <p>
384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * The class storing the parse result to custom datastruct:
394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * {@link VNode}, and {@link PropertyNode}.
404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * Maybe several vcard instance, so use vNodeList to store.
414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * </p>
424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * <p>
434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * This is called VNode, not VCardNode, since it was used for expressing vCalendar (iCal).
444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * </p>
454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */
461680191a2a208fd61123810a88ce9def83e222baDaisuke Miyakawapublic class VNodeBuilder implements VCardInterpreter {
4748dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa    private static String LOG_TAG = "VNodeBuilder";
4848dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa
4948dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa    private List<VNode> mVNodeList = new ArrayList<VNode>();
504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    private VNode mCurrentVNode;
514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    /**
534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa     * The charset using which VParser parses the text.
544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa     */
554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    private String mSourceCharset;
564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    /**
584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa     * The charset with which byte array is encoded to String.
594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa     */
604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    private String mTargetCharset;
6148dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa
624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    private boolean mStrictLineBreakParsing;
6348dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa
644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public VNodeBuilder() {
654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        this(VCardConfig.DEFAULT_IMPORT_CHARSET, false);
664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public VNodeBuilder(String targetCharset, boolean strictLineBreakParsing) {
694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        mSourceCharset = VCardConfig.DEFAULT_INTERMEDIATE_CHARSET;
704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (targetCharset != null) {
714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            mTargetCharset = targetCharset;
724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        } else {
734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            mTargetCharset = VCardConfig.DEFAULT_IMPORT_CHARSET;
744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        mStrictLineBreakParsing = strictLineBreakParsing;
764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
7848dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa    @Override
791de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public void onVCardStarted() {
804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
8248dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa    @Override
831de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public void onVCardEnded() {
844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
8648dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa    @Override
871de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public void onEntryStarted() {
8848dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa        mCurrentVNode = new VNode();
8948dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa        mVNodeList.add(mCurrentVNode);
904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
9248dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa    @Override
931de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public void onEntryEnded() {
9448dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa        int lastIndex = mVNodeList.size() - 1;
9548dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa        mVNodeList.remove(lastIndex--);
9648dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa        mCurrentVNode = lastIndex >= 0 ? mVNodeList.get(lastIndex) : null;
974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
984199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
9948dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa    @Override
1001de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public void onPropertyCreated(VCardProperty property) {
1011de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        // TODO: remove PropertyNode.
1021de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        PropertyNode propNode = new PropertyNode();
1031de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        propNode.propName = property.getName();
1041de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        List<String> groupList = property.getGroupList();
1051de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        if (groupList != null) {
1061de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            propNode.propGroupSet.addAll(groupList);
1074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
1081de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        Map<String, Collection<String>> propertyParameterMap = property.getParameterMap();
1091de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        for (String paramType : propertyParameterMap.keySet()) {
1101de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            Collection<String> paramValueList = propertyParameterMap.get(paramType);
1111de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (paramType.equalsIgnoreCase("TYPE")) {
1121de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                propNode.paramMap_TYPE.addAll(paramValueList);
1131de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            } else {
1141de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                for (String paramValue : paramValueList) {
1151de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    propNode.paramMap.put(paramType, paramValue);
1161de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                }
1174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
1184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
11948dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa
1201de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        // TODO: just redundant
12148dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa
1221de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        if (property.getRawValue() == null) {
1231de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            propNode.propValue_bytes = null;
1241de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            propNode.propValue_vector.clear();
1251de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            propNode.propValue_vector.add("");
1261de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            propNode.propValue = "";
1271de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            return;
1284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
12948dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa
1301de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        final List<String> values = property.getValueList();
1311de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        if (values == null || values.size() == 0) {
1321de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            propNode.propValue_vector.clear();
1331de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            propNode.propValue_vector.add("");
1341de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            propNode.propValue = "";
1351de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        } else {
1361de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            propNode.propValue_vector.addAll(values);
1371de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            propNode.propValue = listToString(propNode.propValue_vector);
1384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
1391de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        propNode.propValue_bytes = property.getByteValue();
1404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
1411de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        mCurrentVNode.propList.add(propNode);
1424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
1434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
1444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    private String listToString(List<String> list){
1454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        int size = list.size();
1464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (size > 1) {
1474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            StringBuilder typeListB = new StringBuilder();
1484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            for (String type : list) {
1494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                typeListB.append(type).append(";");
1504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
1514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            int len = typeListB.length();
1524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            if (len > 0 && typeListB.charAt(len - 1) == ';') {
1534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                return typeListB.substring(0, len - 1);
1544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
1554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            return typeListB.toString();
1564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        } else if (size == 1) {
1574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            return list.get(0);
1584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        } else {
1594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            return "";
1604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
1614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
16248dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa
1634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public String getResult(){
1644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        throw new RuntimeException("Not supported");
1654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
16648dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa
16748dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa    public List<VNode> getVNodeList() {
16848dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa        return mVNodeList;
16948dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa    }
17048dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa
17148dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa    public VNode getCurrentVNode() {
17248dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa        return mCurrentVNode;
17348dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa    }
1744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa}
175