1/* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16package android.pim.vcard; 17 18import android.content.ContentValues; 19import android.pim.vcard.VCardEntry; 20import android.util.Log; 21 22import java.util.ArrayList; 23import java.util.Arrays; 24import java.util.HashSet; 25import java.util.List; 26import java.util.Set; 27 28/** 29 * Previously used in main vCard handling code but now exists only for testing. 30 * 31 * Especially useful for testing parser code (VCardParser), since all properties can be 32 * checked via this class unlike {@link VCardEntry}, which only emits the result of 33 * interpretation of the content of each vCard. We cannot know whether vCard parser or 34 * ContactStruct is wrong withouth this class. 35 */ 36public class PropertyNode { 37 public String propName; 38 public String propValue; 39 public List<String> propValue_vector; 40 41 /** Store value as byte[],after decode. 42 * Used when propValue is encoded by something like BASE64, QUOTED-PRINTABLE, etc. 43 */ 44 public byte[] propValue_bytes; 45 46 /** param store: key=paramType, value=paramValue 47 * Note that currently PropertyNode class does not support multiple param-values 48 * defined in vCard 3.0 (See also RFC 2426). multiple-values are stored as 49 * one String value like "A,B", not ["A", "B"]... 50 * TODO: fix this. 51 */ 52 public ContentValues paramMap; 53 54 /** Only for TYPE=??? param store. */ 55 public Set<String> paramMap_TYPE; 56 57 /** Store group values. Used only in VCard. */ 58 public Set<String> propGroupSet; 59 60 public PropertyNode() { 61 propName = ""; 62 propValue = ""; 63 propValue_vector = new ArrayList<String>(); 64 paramMap = new ContentValues(); 65 paramMap_TYPE = new HashSet<String>(); 66 propGroupSet = new HashSet<String>(); 67 } 68 69 public PropertyNode( 70 String propName, String propValue, List<String> propValue_vector, 71 byte[] propValue_bytes, ContentValues paramMap, Set<String> paramMap_TYPE, 72 Set<String> propGroupSet) { 73 if (propName != null) { 74 this.propName = propName; 75 } else { 76 this.propName = ""; 77 } 78 if (propValue != null) { 79 this.propValue = propValue; 80 } else { 81 this.propValue = ""; 82 } 83 if (propValue_vector != null) { 84 this.propValue_vector = propValue_vector; 85 } else { 86 this.propValue_vector = new ArrayList<String>(); 87 } 88 this.propValue_bytes = propValue_bytes; 89 if (paramMap != null) { 90 this.paramMap = paramMap; 91 } else { 92 this.paramMap = new ContentValues(); 93 } 94 if (paramMap_TYPE != null) { 95 this.paramMap_TYPE = paramMap_TYPE; 96 } else { 97 this.paramMap_TYPE = new HashSet<String>(); 98 } 99 if (propGroupSet != null) { 100 this.propGroupSet = propGroupSet; 101 } else { 102 this.propGroupSet = new HashSet<String>(); 103 } 104 } 105 106 @Override 107 public int hashCode() { 108 // vCard may contain more than one same line in one entry, while HashSet or any other 109 // library which utilize hashCode() does not honor that, so intentionally throw an 110 // Exception. 111 throw new UnsupportedOperationException( 112 "PropertyNode does not provide hashCode() implementation intentionally."); 113 } 114 115 @Override 116 public boolean equals(Object obj) { 117 if (!(obj instanceof PropertyNode)) { 118 return false; 119 } 120 121 PropertyNode node = (PropertyNode)obj; 122 123 if (propName == null || !propName.equals(node.propName)) { 124 return false; 125 } else if (!paramMap_TYPE.equals(node.paramMap_TYPE)) { 126 return false; 127 } else if (!paramMap_TYPE.equals(node.paramMap_TYPE)) { 128 return false; 129 } else if (!propGroupSet.equals(node.propGroupSet)) { 130 return false; 131 } 132 133 if (propValue_bytes != null && Arrays.equals(propValue_bytes, node.propValue_bytes)) { 134 return true; 135 } else { 136 if (!propValue.equals(node.propValue)) { 137 return false; 138 } 139 140 // The value in propValue_vector is not decoded even if it should be 141 // decoded by BASE64 or QUOTED-PRINTABLE. When the size of propValue_vector 142 // is 1, the encoded value is stored in propValue, so we do not have to 143 // check it. 144 return (propValue_vector.equals(node.propValue_vector) || 145 propValue_vector.size() == 1 || 146 node.propValue_vector.size() == 1); 147 } 148 } 149 150 @Override 151 public String toString() { 152 StringBuilder builder = new StringBuilder(); 153 builder.append("propName: "); 154 builder.append(propName); 155 builder.append(", paramMap: "); 156 builder.append(paramMap.toString()); 157 builder.append(", paramMap_TYPE: ["); 158 boolean first = true; 159 for (String elem : paramMap_TYPE) { 160 if (first) { 161 first = false; 162 } else { 163 builder.append(", "); 164 } 165 builder.append('"'); 166 builder.append(elem); 167 builder.append('"'); 168 } 169 builder.append("]"); 170 if (!propGroupSet.isEmpty()) { 171 builder.append(", propGroupSet: ["); 172 first = true; 173 for (String elem : propGroupSet) { 174 if (first) { 175 first = false; 176 } else { 177 builder.append(", "); 178 } 179 builder.append('"'); 180 builder.append(elem); 181 builder.append('"'); 182 } 183 builder.append("]"); 184 } 185 if (propValue_vector != null && propValue_vector.size() > 1) { 186 builder.append(", propValue_vector size: "); 187 builder.append(propValue_vector.size()); 188 } 189 if (propValue_bytes != null) { 190 builder.append(", propValue_bytes size: "); 191 builder.append(propValue_bytes.length); 192 } 193 builder.append(", propValue: \""); 194 builder.append(propValue); 195 builder.append("\""); 196 return builder.toString(); 197 } 198} 199