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 Miyakawa
204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport com.android.vcard.VCardEntry;
214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.util.ArrayList;
234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.util.Arrays;
244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.util.HashSet;
254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.util.List;
264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawaimport java.util.Set;
274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa/**
294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * <p>
304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * The class representing one property (e.g. "N;ENCODING=UTF-8:family:given:middle:prefix:suffix").
314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * </p>
324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * <p>
334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * Previously used in main vCard handling code but now exists only for testing.
344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * </p>
354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * <p>
364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * Especially useful for testing parser code (VCardParser), since all properties can be
374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * checked via this class unlike {@link VCardEntry}, which only emits the result of
384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * interpretation of the content of each vCard. We cannot know whether vCard parser or
394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * {@link VCardEntry} is wrong without this class.
404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa * </p>
414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa */
424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawapublic class PropertyNode {
434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public String propName;
444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public String propValue;
454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public List<String> propValue_vector;
464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    /** Store value as byte[],after decode.
484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa     * Used when propValue is encoded by something like BASE64, QUOTED-PRINTABLE, etc.
494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa     */
504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public byte[] propValue_bytes;
514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    /**
534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa     * param store: key=paramType, value=paramValue
544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa     * Note that currently PropertyNode class does not support multiple param-values
554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa     * defined in vCard 3.0 (See also RFC 2426). multiple-values are stored as
564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa     * one String value like "A,B", not ["A", "B"]...
574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa     * TODO: fix this.
584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa     */
594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public ContentValues paramMap;
604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    /** Only for TYPE=??? param store. */
624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public Set<String> paramMap_TYPE;
634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    /** Store group values. Used only in VCard. */
654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public Set<String> propGroupSet;
664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public PropertyNode() {
684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        propName = "";
694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        propValue = "";
704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        propValue_vector = new ArrayList<String>();
714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        paramMap = new ContentValues();
724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        paramMap_TYPE = new HashSet<String>();
734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        propGroupSet = new HashSet<String>();
744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public PropertyNode(
774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            String propName, String propValue, List<String> propValue_vector,
784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            byte[] propValue_bytes, ContentValues paramMap, Set<String> paramMap_TYPE,
794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            Set<String> propGroupSet) {
804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (propName != null) {
814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            this.propName = propName;
824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        } else {
834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            this.propName = "";
844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (propValue != null) {
864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            this.propValue = propValue;
874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        } else {
884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            this.propValue = "";
894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (propValue_vector != null) {
914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            this.propValue_vector = propValue_vector;
924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        } else {
934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            this.propValue_vector = new ArrayList<String>();
944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        this.propValue_bytes = propValue_bytes;
964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (paramMap != null) {
974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            this.paramMap = paramMap;
984199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        } else {
994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            this.paramMap = new ContentValues();
1004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
1014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (paramMap_TYPE != null) {
1024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            this.paramMap_TYPE = paramMap_TYPE;
1034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        } else {
1044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            this.paramMap_TYPE = new HashSet<String>();
1054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
1064199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (propGroupSet != null) {
1074199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            this.propGroupSet = propGroupSet;
1084199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        } else {
1094199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            this.propGroupSet = new HashSet<String>();
1104199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
1114199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
1124199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
1134199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    @Override
1144199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public int hashCode() {
1154199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        // vCard may contain more than one same line in one entry, while HashSet or any other
1164199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        // library which utilize hashCode() does not honor that, so intentionally throw an
1174199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        // Exception.
1184199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        throw new UnsupportedOperationException(
1194199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                "PropertyNode does not provide hashCode() implementation intentionally.");
1204199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
1214199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
1224199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    @Override
1234199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public boolean equals(Object obj) {
1244199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (!(obj instanceof PropertyNode)) {
1254199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            return false;
1264199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
1274199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
1284199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        PropertyNode node = (PropertyNode)obj;
1294199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
1304199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (propName == null || !propName.equals(node.propName)) {
1314199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            return false;
1324199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        } else if (!paramMap_TYPE.equals(node.paramMap_TYPE)) {
1334199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            return false;
1344199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        } else if (!paramMap_TYPE.equals(node.paramMap_TYPE)) {
1354199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            return false;
1364199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        } else if (!propGroupSet.equals(node.propGroupSet)) {
1374199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            return false;
1384199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
1394199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
1404199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (propValue_bytes != null && Arrays.equals(propValue_bytes, node.propValue_bytes)) {
1414199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            return true;
1424199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        } else {
1434199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            if (!propValue.equals(node.propValue)) {
1444199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                return false;
1454199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
1464199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
1474199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            // The value in propValue_vector is not decoded even if it should be
1484199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            // decoded by BASE64 or QUOTED-PRINTABLE. When the size of propValue_vector
1494199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            // is 1, the encoded value is stored in propValue, so we do not have to
1504199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            // check it.
1514199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            return (propValue_vector.equals(node.propValue_vector) ||
1524199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    propValue_vector.size() == 1 ||
1534199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    node.propValue_vector.size() == 1);
1544199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
1554199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
1564199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa
1574199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    @Override
1584199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    public String toString() {
1594199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        StringBuilder builder = new StringBuilder();
1604199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        builder.append("propName: ");
1614199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        builder.append(propName);
1624199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        builder.append(", paramMap: ");
1634199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        builder.append(paramMap.toString());
1644199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        builder.append(", paramMap_TYPE: [");
1654199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        boolean first = true;
1664199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        for (String elem : paramMap_TYPE) {
1674199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            if (first) {
1684199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                first = false;
1694199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            } else {
1704199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                builder.append(", ");
1714199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
1724199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            builder.append('"');
1734199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            builder.append(elem);
1744199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            builder.append('"');
1754199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
1764199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        builder.append("]");
1774199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (!propGroupSet.isEmpty()) {
1784199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            builder.append(", propGroupSet: [");
1794199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            first = true;
1804199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            for (String elem : propGroupSet) {
1814199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                if (first) {
1824199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    first = false;
1834199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                } else {
1844199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                    builder.append(", ");
1854199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                }
1864199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                builder.append('"');
1874199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                builder.append(elem);
1884199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa                builder.append('"');
1894199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            }
1904199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            builder.append("]");
1914199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
1924199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (propValue_vector != null && propValue_vector.size() > 1) {
1934199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            builder.append(", propValue_vector size: ");
1944199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            builder.append(propValue_vector.size());
1954199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
1964199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        if (propValue_bytes != null) {
1974199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            builder.append(", propValue_bytes size: ");
1984199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa            builder.append(propValue_bytes.length);
1994199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        }
2004199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        builder.append(", propValue: \"");
2014199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        builder.append(propValue);
2024199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        builder.append("\"");
2034199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa        return builder.toString();
2044199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa    }
2054199c54c527330ac01699b176e7bca186a3aa3a4Daisuke Miyakawa}
206