VNodeBuilder.java revision 48dd8e86a81d2ab40eb762975c8211c225002bf0
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
184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.content.ContentValues;
194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.util.Base64;
204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.util.CharsetUtils;
214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport android.util.Log;
224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport com.android.vcard.VCardConfig;
244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport com.android.vcard.VCardInterpreter;
254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport com.android.vcard.VCardUtils;
264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.io.UnsupportedEncodingException;
284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.nio.ByteBuffer;
294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.nio.charset.Charset;
304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.util.ArrayList;
314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.util.List;
324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa/**
344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * <p>
354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * The class storing the parse result to custom datastruct:
364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * {@link VNode}, and {@link PropertyNode}.
374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * Maybe several vcard instance, so use vNodeList to store.
384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * </p>
394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * <p>
404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * This is called VNode, not VCardNode, since it was used for expressing vCalendar (iCal).
414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * </p>
424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */
431680191a2a208fd61123810a88ce9def83e222baDaisuke Miyakawapublic class VNodeBuilder implements VCardInterpreter {
4448dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa    private static String LOG_TAG = "VNodeBuilder";
4548dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa
4648dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa    private List<VNode> mVNodeList = new ArrayList<VNode>();
474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    private VNode mCurrentVNode;
484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    private PropertyNode mCurrentPropNode;
494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    private String mCurrentParamType;
504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    /**
524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa     * The charset using which VParser parses the text.
534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa     */
544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    private String mSourceCharset;
554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    /**
574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa     * The charset with which byte array is encoded to String.
584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa     */
594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    private String mTargetCharset;
6048dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa
614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    private boolean mStrictLineBreakParsing;
6248dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa
634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public VNodeBuilder() {
644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        this(VCardConfig.DEFAULT_IMPORT_CHARSET, false);
654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public VNodeBuilder(String targetCharset, boolean strictLineBreakParsing) {
684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        mSourceCharset = VCardConfig.DEFAULT_INTERMEDIATE_CHARSET;
694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (targetCharset != null) {
704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            mTargetCharset = targetCharset;
714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        } else {
724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            mTargetCharset = VCardConfig.DEFAULT_IMPORT_CHARSET;
734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        mStrictLineBreakParsing = strictLineBreakParsing;
754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
7748dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa    @Override
784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public void start() {
794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
8148dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa    @Override
824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public void end() {
834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
8548dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa    @Override
864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public void startEntry() {
8748dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa        mCurrentVNode = new VNode();
8848dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa        mVNodeList.add(mCurrentVNode);
894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
9148dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa    @Override
924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public void endEntry() {
9348dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa        int lastIndex = mVNodeList.size() - 1;
9448dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa        mVNodeList.remove(lastIndex--);
9548dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa        mCurrentVNode = lastIndex >= 0 ? mVNodeList.get(lastIndex) : null;
964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
9848dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa    @Override
994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public void startProperty() {
1004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        mCurrentPropNode = new PropertyNode();
1014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
1024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
10348dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa    @Override
1044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public void endProperty() {
1054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        mCurrentVNode.propList.add(mCurrentPropNode);
1064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
10748dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa
10848dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa    @Override
1094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public void propertyName(String name) {
1104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        mCurrentPropNode.propName = name;
1114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
1124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
11348dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa    @Override
1144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public void propertyGroup(String group) {
1154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        mCurrentPropNode.propGroupSet.add(group);
1164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
11748dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa
11848dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa    @Override
1194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public void propertyParamType(String type) {
1204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        mCurrentParamType = type;
1214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
1224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
12348dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa    @Override
1244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public void propertyParamValue(String value) {
12558ca5f9943bb5c8aeeab3150ac96f1143dfd86baDaisuke Miyakawa        if (!VCardUtils.containsOnlyAlphaDigitHyphen(value)) {
12658ca5f9943bb5c8aeeab3150ac96f1143dfd86baDaisuke Miyakawa            value = VCardUtils.convertStringCharset(value,
12758ca5f9943bb5c8aeeab3150ac96f1143dfd86baDaisuke Miyakawa                    VCardConfig.DEFAULT_INTERMEDIATE_CHARSET,
12858ca5f9943bb5c8aeeab3150ac96f1143dfd86baDaisuke Miyakawa                    VCardConfig.DEFAULT_IMPORT_CHARSET);
12958ca5f9943bb5c8aeeab3150ac96f1143dfd86baDaisuke Miyakawa        }
13058ca5f9943bb5c8aeeab3150ac96f1143dfd86baDaisuke Miyakawa
1314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (mCurrentParamType == null ||
1324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                mCurrentParamType.equalsIgnoreCase("TYPE")) {
1334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            mCurrentPropNode.paramMap_TYPE.add(value);
1344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        } else {
1354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            mCurrentPropNode.paramMap.put(mCurrentParamType, value);
1364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
1374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
1384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        mCurrentParamType = null;
1394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
1404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
1414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    private String encodeString(String originalString, String targetCharset) {
1424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (mSourceCharset.equalsIgnoreCase(targetCharset)) {
1434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            return originalString;
1444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
1454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        Charset charset = Charset.forName(mSourceCharset);
1464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        ByteBuffer byteBuffer = charset.encode(originalString);
1474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        // byteBuffer.array() "may" return byte array which is larger than
1484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        // byteBuffer.remaining(). Here, we keep on the safe side.
1494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        byte[] bytes = new byte[byteBuffer.remaining()];
1504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        byteBuffer.get(bytes);
1514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        try {
1524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            return new String(bytes, targetCharset);
1534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        } catch (UnsupportedEncodingException e) {
1544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            Log.e(LOG_TAG, "Failed to encode: charset=" + targetCharset);
1554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            return null;
1564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
1574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
15848dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa
1594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    private String handleOneValue(String value, String targetCharset, String encoding) {
1604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (encoding != null) {
1614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            encoding = encoding.toUpperCase();
1624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            if (encoding.equals("BASE64") || encoding.equals("B")) {
1634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                // Assume BASE64 is used only when the number of values is 1.
1644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                mCurrentPropNode.propValue_bytes = Base64.decode(value.getBytes(), Base64.NO_WRAP);
1654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                return value;
1664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            } else if (encoding.equals("QUOTED-PRINTABLE")) {
1674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                return VCardUtils.parseQuotedPrintable(
1684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                        value, mStrictLineBreakParsing, mSourceCharset, targetCharset);
1694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
1704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            // Unknown encoding. Fall back to default.
1714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
1724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        return encodeString(value, targetCharset);
1734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
17448dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa
17548dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa    @Override
1764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public void propertyValues(List<String> values) {
1774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (values == null || values.size() == 0) {
1784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            mCurrentPropNode.propValue_bytes = null;
1794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            mCurrentPropNode.propValue_vector.clear();
1804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            mCurrentPropNode.propValue_vector.add("");
1814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            mCurrentPropNode.propValue = "";
1824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            return;
1834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
18448dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa
1854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        ContentValues paramMap = mCurrentPropNode.paramMap;
18648dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa
18748dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa        String targetCharset = CharsetUtils.nameForDefaultVendor(paramMap.getAsString("CHARSET"));
18848dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa        String encoding = paramMap.getAsString("ENCODING");
18948dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa
1904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (targetCharset == null || targetCharset.length() == 0) {
1914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            targetCharset = mTargetCharset;
1924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
19348dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa
1944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        for (String value : values) {
1954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            mCurrentPropNode.propValue_vector.add(
1964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    handleOneValue(value, targetCharset, encoding));
1974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
1984199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
1994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        mCurrentPropNode.propValue = listToString(mCurrentPropNode.propValue_vector);
2004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
2014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
2024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    private String listToString(List<String> list){
2034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        int size = list.size();
2044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (size > 1) {
2054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            StringBuilder typeListB = new StringBuilder();
2064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            for (String type : list) {
2074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                typeListB.append(type).append(";");
2084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
2094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            int len = typeListB.length();
2104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            if (len > 0 && typeListB.charAt(len - 1) == ';') {
2114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                return typeListB.substring(0, len - 1);
2124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
2134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            return typeListB.toString();
2144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        } else if (size == 1) {
2154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            return list.get(0);
2164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        } else {
2174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            return "";
2184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
2194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
22048dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa
2214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public String getResult(){
2224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        throw new RuntimeException("Not supported");
2234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
22448dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa
22548dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa    public List<VNode> getVNodeList() {
22648dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa        return mVNodeList;
22748dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa    }
22848dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa
22948dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa    public VNode getCurrentVNode() {
23048dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa        return mCurrentVNode;
23148dd8e86a81d2ab40eb762975c8211c225002bf0Daisuke Miyakawa    }
2324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa}
233