11de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa/*
21de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa * Copyright (C) 2011 The Android Open Source Project
31de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa *
41de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa * Licensed under the Apache License, Version 2.0 (the "License");
51de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa * you may not use this file except in compliance with the License.
61de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa * You may obtain a copy of the License at
71de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa *
81de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa *      http://www.apache.org/licenses/LICENSE-2.0
91de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa *
101de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa * Unless required by applicable law or agreed to in writing, software
111de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa * distributed under the License is distributed on an "AS IS" BASIS,
121de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa * See the License for the specific language governing permissions and
141de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa * limitations under the License.
151de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa */
161de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawapackage com.android.vcard;
171de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
181de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawaimport android.util.Log;
191de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
201de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawaimport java.util.ArrayList;
211de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawaimport java.util.Arrays;
221de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawaimport java.util.Collection;
231de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawaimport java.util.HashMap;
241de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawaimport java.util.HashSet;
251de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawaimport java.util.List;
261de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawaimport java.util.Map;
271de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
281de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa/**
291de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa * Represents vCard's property, or logical "one line" of each vCard entry.
301de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa *
311de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa * e.g.
321de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa * Given a vCard below, objects for <code>N:name</code>, <code>TEL:1111111111</code> are
331de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa * "property".
341de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa *
351de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa * <code>
361de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa * BEGIN:VCARD
371de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa * N:name
381de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa * TEL:1111111111
391de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa * END:VCARD
401de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa * </code>
411de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa *
421de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa * vCard's property has three elements: name, parameter (or param), and value. Name is the name
431de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa * of each property. Parameter or param is additional information for the property. Value is one
441de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa * or multiple values representing the parameter.
451de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa *
461de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa * e.g.
471de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa * <code>N;CHARSET=UTF-8:Joe;Due;M.;Mr.;Ph.D.</code>, has "N" for name, "CHALSET=UTF-8" for param,
481de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa * and "Joe;Due;M.;Mr.;Ph.D." for value.
491de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa *
501de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa * Usually params are represented as "key=value" pair, but not always
511de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa * (The property <code>TEL;WORK;VOICE:(111) 555-1212</code> has two params without key "TYPE",
521de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa * which are same as "TYPE=WORK" and "TYPE=VOICE". In vCard 3.0, we can even express them as
531de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa * "TYPE=WORK,VOICE").
541de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa *
551de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa * Sometimes (not always) value can be separated by semi-colon. In the example above "Joe;Due;;;"
561de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa * should be interpreted as five strings: "Joe" (for family name), "Due" (for given name), "M."
571de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa * (for middle name), "Mr." (for prefix), and "Ph.D." (for suffix). Whether the value is
581de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa * separable or not is specified by vCard specs.
591de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa */
601de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawapublic class VCardProperty {
611de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    private static final String LOG_TAG = VCardConstants.LOG_TAG;
621de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    private String mName;
631de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    private List<String> mGroupList;
641de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
651de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    private Map<String, Collection<String>> mParameterMap =
661de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            new HashMap<String, Collection<String>>();
671de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    private String mRawValue;
681de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
691de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    private List<String> mValueList;
701de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    private byte[] mByteValue;
711de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
721de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public void setName(String name) {
731de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        if (mName != null) {
741de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            Log.w(LOG_TAG, String.format("Property name is re-defined " +
751de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                    "(existing: %s, requested: %s", mName, name));
761de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
771de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        mName = name;
781de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    }
791de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
801de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public void addGroup(String group) {
811de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        if (mGroupList == null) {
821de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mGroupList = new ArrayList<String>();
831de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
841de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        mGroupList.add(group);
851de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    }
861de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
871de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public void setParameter(final String paramName, final String paramValue) {
881de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        mParameterMap.clear();
891de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        addParameter(paramName, paramValue);
901de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    }
911de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
921de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public void addParameter(final String paramName, final String paramValue) {
931de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        Collection<String> values;
941de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        if (!mParameterMap.containsKey(paramName)) {
951de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            if (paramName.equals("TYPE")) {
961de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                values = new HashSet<String>();
971de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            } else {
981de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa                values = new ArrayList<String>();
991de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            }
1001de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mParameterMap.put(paramName, values);
1011de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        } else {
1021de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            values = mParameterMap.get(paramName);
1031de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
1041de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        values.add(paramValue);
1051de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    }
1061de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
1071de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public void setRawValue(String rawValue) {
1081de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        mRawValue = rawValue;
1091de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    }
1101de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
1111de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    // TODO: would be much better to have translateRawValue() functionality instead of forcing
1121de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    // VCardParserImpl does this job.
1131de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
1141de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public void setValues(String... propertyValues) {
1151de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        mValueList = Arrays.asList(propertyValues);
1161de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    }
1171de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
1181de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public void setValues(List<String> propertyValueList) {
1191de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        mValueList = propertyValueList;
1201de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    }
1211de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
1221de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public void addValues(String... propertyValues) {
1231de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        if (mValueList == null) {
1241de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mValueList = Arrays.asList(propertyValues);
1251de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        } else {
1261de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mValueList.addAll(Arrays.asList(propertyValues));
1271de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
1281de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    }
1291de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
1301de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public void addValues(List<String> propertyValueList) {
1311de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        if (mValueList == null) {
1321de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mValueList = new ArrayList<String>(propertyValueList);
1331de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        } else {
1341de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa            mValueList.addAll(propertyValueList);
1351de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        }
1361de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    }
1371de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
1381de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public void setByteValue(byte[] byteValue) {
1391de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        mByteValue = byteValue;
1401de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    }
1411de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
1421de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public String getName() {
1431de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        return mName;
1441de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    }
1451de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
1461de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public List<String> getGroupList() {
1471de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        return mGroupList;
1481de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    }
1491de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
1501de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public Map<String, Collection<String>> getParameterMap() {
1511de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        return mParameterMap;
1521de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    }
1531de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
1541de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public Collection<String> getParameters(String type) {
1551de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        return mParameterMap.get(type);
1561de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    }
1571de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
1581de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public String getRawValue() {
1591de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        return mRawValue;
1601de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    }
1611de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
1621de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public List<String> getValueList() {
1631de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        return mValueList;
1641de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    }
1651de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
1661de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    public byte[] getByteValue() {
1671de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa        return mByteValue;
1681de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa    }
1691de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa}
1701de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
1711de396f6df89363169d3a2e61a61fa98d12c1ef8Daisuke Miyakawa
172