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 */ 16 package android.pim.vcard.test_utils; 17 18 import android.content.ContentValues; 19 import android.pim.vcard.VCardEntry; 20 21 import java.util.ArrayList; 22 import java.util.Arrays; 23 import java.util.HashSet; 24 import java.util.List; 25 import java.util.Set; 26 27 /** 28 * <p> 29 * The class representing one property (e.g. "N;ENCODING=UTF-8:family:given:middle:prefix:suffix"). 30 * </p> 31 * <p> 32 * Previously used in main vCard handling code but now exists only for testing. 33 * </p> 34 * <p> 35 * Especially useful for testing parser code (VCardParser), since all properties can be 36 * checked via this class unlike {@link VCardEntry}, which only emits the result of 37 * interpretation of the content of each vCard. We cannot know whether vCard parser or 38 * {@link VCardEntry} is wrong without this class. 39 * </p> 40 */ 41 public class PropertyNode { 42 public String propName; 43 public String propValue; 44 public List<String> propValue_vector; 45 46 /** Store value as byte[],after decode. 47 * Used when propValue is encoded by something like BASE64, QUOTED-PRINTABLE, etc. 48 */ 49 public byte[] propValue_bytes; 50 51 /** 52 * param store: key=paramType, value=paramValue 53 * Note that currently PropertyNode class does not support multiple param-values 54 * defined in vCard 3.0 (See also RFC 2426). multiple-values are stored as 55 * one String value like "A,B", not ["A", "B"]... 56 * TODO: fix this. 57 */ 58 public ContentValues paramMap; 59 60 /** Only for TYPE=??? param store. */ 61 public Set<String> paramMap_TYPE; 62 63 /** Store group values. Used only in VCard. */ 64 public Set<String> propGroupSet; 65 66 public PropertyNode() { 67 propName = ""; 68 propValue = ""; 69 propValue_vector = new ArrayList<String>(); 70 paramMap = new ContentValues(); 71 paramMap_TYPE = new HashSet<String>(); 72 propGroupSet = new HashSet<String>(); 73 } 74 75 public PropertyNode( 76 String propName, String propValue, List<String> propValue_vector, 77 byte[] propValue_bytes, ContentValues paramMap, Set<String> paramMap_TYPE, 78 Set<String> propGroupSet) { 79 if (propName != null) { 80 this.propName = propName; 81 } else { 82 this.propName = ""; 83 } 84 if (propValue != null) { 85 this.propValue = propValue; 86 } else { 87 this.propValue = ""; 88 } 89 if (propValue_vector != null) { 90 this.propValue_vector = propValue_vector; 91 } else { 92 this.propValue_vector = new ArrayList<String>(); 93 } 94 this.propValue_bytes = propValue_bytes; 95 if (paramMap != null) { 96 this.paramMap = paramMap; 97 } else { 98 this.paramMap = new ContentValues(); 99 } 100 if (paramMap_TYPE != null) { 101 this.paramMap_TYPE = paramMap_TYPE; 102 } else { 103 this.paramMap_TYPE = new HashSet<String>(); 104 } 105 if (propGroupSet != null) { 106 this.propGroupSet = propGroupSet; 107 } else { 108 this.propGroupSet = new HashSet<String>(); 109 } 110 } 111 112 @Override 113 public int hashCode() { 114 // vCard may contain more than one same line in one entry, while HashSet or any other 115 // library which utilize hashCode() does not honor that, so intentionally throw an 116 // Exception. 117 throw new UnsupportedOperationException( 118 "PropertyNode does not provide hashCode() implementation intentionally."); 119 } 120 121 @Override 122 public boolean equals(Object obj) { 123 if (!(obj instanceof PropertyNode)) { 124 return false; 125 } 126 127 PropertyNode node = (PropertyNode)obj; 128 129 if (propName == null || !propName.equals(node.propName)) { 130 return false; 131 } else if (!paramMap_TYPE.equals(node.paramMap_TYPE)) { 132 return false; 133 } else if (!paramMap_TYPE.equals(node.paramMap_TYPE)) { 134 return false; 135 } else if (!propGroupSet.equals(node.propGroupSet)) { 136 return false; 137 } 138 139 if (propValue_bytes != null && Arrays.equals(propValue_bytes, node.propValue_bytes)) { 140 return true; 141 } else { 142 if (!propValue.equals(node.propValue)) { 143 return false; 144 } 145 146 // The value in propValue_vector is not decoded even if it should be 147 // decoded by BASE64 or QUOTED-PRINTABLE. When the size of propValue_vector 148 // is 1, the encoded value is stored in propValue, so we do not have to 149 // check it. 150 return (propValue_vector.equals(node.propValue_vector) || 151 propValue_vector.size() == 1 || 152 node.propValue_vector.size() == 1); 153 } 154 } 155 156 @Override 157 public String toString() { 158 StringBuilder builder = new StringBuilder(); 159 builder.append("propName: "); 160 builder.append(propName); 161 builder.append(", paramMap: "); 162 builder.append(paramMap.toString()); 163 builder.append(", paramMap_TYPE: ["); 164 boolean first = true; 165 for (String elem : paramMap_TYPE) { 166 if (first) { 167 first = false; 168 } else { 169 builder.append(", "); 170 } 171 builder.append('"'); 172 builder.append(elem); 173 builder.append('"'); 174 } 175 builder.append("]"); 176 if (!propGroupSet.isEmpty()) { 177 builder.append(", propGroupSet: ["); 178 first = true; 179 for (String elem : propGroupSet) { 180 if (first) { 181 first = false; 182 } else { 183 builder.append(", "); 184 } 185 builder.append('"'); 186 builder.append(elem); 187 builder.append('"'); 188 } 189 builder.append("]"); 190 } 191 if (propValue_vector != null && propValue_vector.size() > 1) { 192 builder.append(", propValue_vector size: "); 193 builder.append(propValue_vector.size()); 194 } 195 if (propValue_bytes != null) { 196 builder.append(", propValue_bytes size: "); 197 builder.append(propValue_bytes.length); 198 } 199 builder.append(", propValue: \""); 200 builder.append(propValue); 201 builder.append("\""); 202 return builder.toString(); 203 } 204 } 205