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