17674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa/*
27674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa * Copyright (C) 2009 The Android Open Source Project
37674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa *
47674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa * Licensed under the Apache License, Version 2.0 (the "License");
57674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa * you may not use this file except in compliance with the License.
67674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa * You may obtain a copy of the License at
77674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa *
87674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa *      http://www.apache.org/licenses/LICENSE-2.0
97674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa *
107674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa * Unless required by applicable law or agreed to in writing, software
117674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa * distributed under the License is distributed on an "AS IS" BASIS,
127674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
137674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa * See the License for the specific language governing permissions and
147674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa * limitations under the License.
157674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa */
161a44d5dcabc18cd5ef111f732ccff91683a1a093Neal Nguyenpackage android.pim.vcard;
177674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa
187674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawaimport android.content.ContentValues;
195a1f2d2de026b582fbe8b1a46a83ad33760a2c48Daisuke Miyakawaimport android.pim.vcard.VCardEntry;
205a1f2d2de026b582fbe8b1a46a83ad33760a2c48Daisuke Miyakawaimport android.util.Log;
217674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa
227674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawaimport java.util.ArrayList;
237674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawaimport java.util.Arrays;
247674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawaimport java.util.HashSet;
257674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawaimport java.util.List;
267674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawaimport java.util.Set;
277674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa
287674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa/**
295c3e687965a49e4e54196a049337544a6eed61d9Daisuke Miyakawa * Previously used in main vCard handling code but now exists only for testing.
305c3e687965a49e4e54196a049337544a6eed61d9Daisuke Miyakawa *
315c3e687965a49e4e54196a049337544a6eed61d9Daisuke Miyakawa * Especially useful for testing parser code (VCardParser), since all properties can be
325a1f2d2de026b582fbe8b1a46a83ad33760a2c48Daisuke Miyakawa * checked via this class unlike {@link VCardEntry}, which only emits the result of
335c3e687965a49e4e54196a049337544a6eed61d9Daisuke Miyakawa * interpretation of the content of each vCard. We cannot know whether vCard parser or
345c3e687965a49e4e54196a049337544a6eed61d9Daisuke Miyakawa * ContactStruct is wrong withouth this class.
357674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa */
367674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawapublic class PropertyNode {
377674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa    public String propName;
387674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa    public String propValue;
397674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa    public List<String> propValue_vector;
407674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa
417674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa    /** Store value as byte[],after decode.
427674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa     * Used when propValue is encoded by something like BASE64, QUOTED-PRINTABLE, etc.
437674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa     */
447674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa    public byte[] propValue_bytes;
457674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa
467674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa    /** param store: key=paramType, value=paramValue
477674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa     * Note that currently PropertyNode class does not support multiple param-values
487674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa     * defined in vCard 3.0 (See also RFC 2426). multiple-values are stored as
497674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa     * one String value like "A,B", not ["A", "B"]...
507674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa     * TODO: fix this.
517674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa     */
527674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa    public ContentValues paramMap;
537674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa
547674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa    /** Only for TYPE=??? param store. */
557674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa    public Set<String> paramMap_TYPE;
567674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa
577674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa    /** Store group values. Used only in VCard. */
587674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa    public Set<String> propGroupSet;
597674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa
607674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa    public PropertyNode() {
617674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa        propName = "";
627674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa        propValue = "";
637674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa        propValue_vector = new ArrayList<String>();
647674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa        paramMap = new ContentValues();
657674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa        paramMap_TYPE = new HashSet<String>();
667674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa        propGroupSet = new HashSet<String>();
677674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa    }
687674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa
697674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa    public PropertyNode(
707674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa            String propName, String propValue, List<String> propValue_vector,
717674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa            byte[] propValue_bytes, ContentValues paramMap, Set<String> paramMap_TYPE,
727674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa            Set<String> propGroupSet) {
737674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa        if (propName != null) {
747674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa            this.propName = propName;
757674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa        } else {
767674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa            this.propName = "";
777674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa        }
787674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa        if (propValue != null) {
797674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa            this.propValue = propValue;
807674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa        } else {
817674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa            this.propValue = "";
827674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa        }
837674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa        if (propValue_vector != null) {
847674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa            this.propValue_vector = propValue_vector;
857674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa        } else {
867674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa            this.propValue_vector = new ArrayList<String>();
877674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa        }
887674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa        this.propValue_bytes = propValue_bytes;
897674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa        if (paramMap != null) {
907674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa            this.paramMap = paramMap;
917674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa        } else {
927674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa            this.paramMap = new ContentValues();
937674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa        }
947674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa        if (paramMap_TYPE != null) {
957674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa            this.paramMap_TYPE = paramMap_TYPE;
967674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa        } else {
977674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa            this.paramMap_TYPE = new HashSet<String>();
987674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa        }
997674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa        if (propGroupSet != null) {
1007674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa            this.propGroupSet = propGroupSet;
1017674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa        } else {
1027674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa            this.propGroupSet = new HashSet<String>();
1037674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa        }
1047674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa    }
1057674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa
1067674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa    @Override
107ba2b21bee817c58e9b22c57e02ef6201e1cda1bdDaisuke Miyakawa    public int hashCode() {
108ba2b21bee817c58e9b22c57e02ef6201e1cda1bdDaisuke Miyakawa        // vCard may contain more than one same line in one entry, while HashSet or any other
109ba2b21bee817c58e9b22c57e02ef6201e1cda1bdDaisuke Miyakawa        // library which utilize hashCode() does not honor that, so intentionally throw an
110ba2b21bee817c58e9b22c57e02ef6201e1cda1bdDaisuke Miyakawa        // Exception.
111ba2b21bee817c58e9b22c57e02ef6201e1cda1bdDaisuke Miyakawa        throw new UnsupportedOperationException(
112ba2b21bee817c58e9b22c57e02ef6201e1cda1bdDaisuke Miyakawa                "PropertyNode does not provide hashCode() implementation intentionally.");
113ba2b21bee817c58e9b22c57e02ef6201e1cda1bdDaisuke Miyakawa    }
114ba2b21bee817c58e9b22c57e02ef6201e1cda1bdDaisuke Miyakawa
115ba2b21bee817c58e9b22c57e02ef6201e1cda1bdDaisuke Miyakawa    @Override
1167674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa    public boolean equals(Object obj) {
1177674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa        if (!(obj instanceof PropertyNode)) {
1187674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa            return false;
1197674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa        }
1207674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa
1217674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa        PropertyNode node = (PropertyNode)obj;
1227674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa
1237674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa        if (propName == null || !propName.equals(node.propName)) {
1247674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa            return false;
125839c036444c8a5335cc557e174acc7ee28baafc4Daisuke Miyakawa        } else if (!paramMap_TYPE.equals(node.paramMap_TYPE)) {
1267674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa            return false;
127839c036444c8a5335cc557e174acc7ee28baafc4Daisuke Miyakawa        } else if (!paramMap_TYPE.equals(node.paramMap_TYPE)) {
1287674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa            return false;
1297674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa        } else if (!propGroupSet.equals(node.propGroupSet)) {
1307674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa            return false;
1317674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa        }
132839c036444c8a5335cc557e174acc7ee28baafc4Daisuke Miyakawa
1337674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa        if (propValue_bytes != null && Arrays.equals(propValue_bytes, node.propValue_bytes)) {
1347674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa            return true;
1357674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa        } else {
1367674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa            if (!propValue.equals(node.propValue)) {
1377674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa                return false;
1387674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa            }
1397674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa
1407674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa            // The value in propValue_vector is not decoded even if it should be
1417674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa            // decoded by BASE64 or QUOTED-PRINTABLE. When the size of propValue_vector
1427674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa            // is 1, the encoded value is stored in propValue, so we do not have to
1437674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa            // check it.
1447674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa            return (propValue_vector.equals(node.propValue_vector) ||
1457674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa                    propValue_vector.size() == 1 ||
1467674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa                    node.propValue_vector.size() == 1);
1477674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa        }
1487674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa    }
1497674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa
1507674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa    @Override
1517674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa    public String toString() {
1527674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa        StringBuilder builder = new StringBuilder();
1537674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa        builder.append("propName: ");
1547674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa        builder.append(propName);
1557674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa        builder.append(", paramMap: ");
1567674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa        builder.append(paramMap.toString());
1575a1f2d2de026b582fbe8b1a46a83ad33760a2c48Daisuke Miyakawa        builder.append(", paramMap_TYPE: [");
1585a1f2d2de026b582fbe8b1a46a83ad33760a2c48Daisuke Miyakawa        boolean first = true;
1595a1f2d2de026b582fbe8b1a46a83ad33760a2c48Daisuke Miyakawa        for (String elem : paramMap_TYPE) {
1605a1f2d2de026b582fbe8b1a46a83ad33760a2c48Daisuke Miyakawa            if (first) {
1615a1f2d2de026b582fbe8b1a46a83ad33760a2c48Daisuke Miyakawa                first = false;
1625a1f2d2de026b582fbe8b1a46a83ad33760a2c48Daisuke Miyakawa            } else {
1635a1f2d2de026b582fbe8b1a46a83ad33760a2c48Daisuke Miyakawa                builder.append(", ");
1645a1f2d2de026b582fbe8b1a46a83ad33760a2c48Daisuke Miyakawa            }
1655a1f2d2de026b582fbe8b1a46a83ad33760a2c48Daisuke Miyakawa            builder.append('"');
1665a1f2d2de026b582fbe8b1a46a83ad33760a2c48Daisuke Miyakawa            builder.append(elem);
1675a1f2d2de026b582fbe8b1a46a83ad33760a2c48Daisuke Miyakawa            builder.append('"');
1685a1f2d2de026b582fbe8b1a46a83ad33760a2c48Daisuke Miyakawa        }
1695a1f2d2de026b582fbe8b1a46a83ad33760a2c48Daisuke Miyakawa        builder.append("]");
1705a1f2d2de026b582fbe8b1a46a83ad33760a2c48Daisuke Miyakawa        if (!propGroupSet.isEmpty()) {
1715a1f2d2de026b582fbe8b1a46a83ad33760a2c48Daisuke Miyakawa            builder.append(", propGroupSet: [");
172839c036444c8a5335cc557e174acc7ee28baafc4Daisuke Miyakawa            first = true;
1735a1f2d2de026b582fbe8b1a46a83ad33760a2c48Daisuke Miyakawa            for (String elem : propGroupSet) {
1745a1f2d2de026b582fbe8b1a46a83ad33760a2c48Daisuke Miyakawa                if (first) {
1755a1f2d2de026b582fbe8b1a46a83ad33760a2c48Daisuke Miyakawa                    first = false;
1765a1f2d2de026b582fbe8b1a46a83ad33760a2c48Daisuke Miyakawa                } else {
1775a1f2d2de026b582fbe8b1a46a83ad33760a2c48Daisuke Miyakawa                    builder.append(", ");
1785a1f2d2de026b582fbe8b1a46a83ad33760a2c48Daisuke Miyakawa                }
1795a1f2d2de026b582fbe8b1a46a83ad33760a2c48Daisuke Miyakawa                builder.append('"');
1805a1f2d2de026b582fbe8b1a46a83ad33760a2c48Daisuke Miyakawa                builder.append(elem);
1815a1f2d2de026b582fbe8b1a46a83ad33760a2c48Daisuke Miyakawa                builder.append('"');
1825a1f2d2de026b582fbe8b1a46a83ad33760a2c48Daisuke Miyakawa            }
1835a1f2d2de026b582fbe8b1a46a83ad33760a2c48Daisuke Miyakawa            builder.append("]");
1845a1f2d2de026b582fbe8b1a46a83ad33760a2c48Daisuke Miyakawa        }
1857674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa        if (propValue_vector != null && propValue_vector.size() > 1) {
1867674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa            builder.append(", propValue_vector size: ");
1877674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa            builder.append(propValue_vector.size());
1887674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa        }
1897674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa        if (propValue_bytes != null) {
1907674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa            builder.append(", propValue_bytes size: ");
1917674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa            builder.append(propValue_bytes.length);
1927674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa        }
193839c036444c8a5335cc557e174acc7ee28baafc4Daisuke Miyakawa        builder.append(", propValue: \"");
1947674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa        builder.append(propValue);
195839c036444c8a5335cc557e174acc7ee28baafc4Daisuke Miyakawa        builder.append("\"");
1967674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa        return builder.toString();
1977674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa    }
1987674b81a05a8aa0b7a1be1bb04e041f6d2106fe2Daisuke Miyakawa}
199