1 /* 2 * Copyright (C) 2007 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 17 package android.content; 18 19 import android.os.Parcel; 20 import android.os.Parcelable; 21 import android.util.Log; 22 23 import java.util.ArrayList; 24 import java.util.HashMap; 25 import java.util.Map; 26 import java.util.Set; 27 28 /** 29 * This class is used to store a set of values that the {@link ContentResolver} 30 * can process. 31 */ 32 public final class ContentValues implements Parcelable { 33 public static final String TAG = "ContentValues"; 34 35 /** Holds the actual values */ 36 private HashMap<String, Object> mValues; 37 38 /** 39 * Creates an empty set of values using the default initial size 40 */ ContentValues()41 public ContentValues() { 42 // Choosing a default size of 8 based on analysis of typical 43 // consumption by applications. 44 mValues = new HashMap<String, Object>(8); 45 } 46 47 /** 48 * Creates an empty set of values using the given initial size 49 * 50 * @param size the initial size of the set of values 51 */ ContentValues(int size)52 public ContentValues(int size) { 53 mValues = new HashMap<String, Object>(size, 1.0f); 54 } 55 56 /** 57 * Creates a set of values copied from the given set 58 * 59 * @param from the values to copy 60 */ ContentValues(ContentValues from)61 public ContentValues(ContentValues from) { 62 mValues = new HashMap<String, Object>(from.mValues); 63 } 64 65 /** 66 * Creates a set of values copied from the given HashMap. This is used 67 * by the Parcel unmarshalling code. 68 * 69 * @param values the values to start with 70 * {@hide} 71 */ ContentValues(HashMap<String, Object> values)72 private ContentValues(HashMap<String, Object> values) { 73 mValues = values; 74 } 75 76 @Override equals(Object object)77 public boolean equals(Object object) { 78 if (!(object instanceof ContentValues)) { 79 return false; 80 } 81 return mValues.equals(((ContentValues) object).mValues); 82 } 83 84 @Override hashCode()85 public int hashCode() { 86 return mValues.hashCode(); 87 } 88 89 /** 90 * Adds a value to the set. 91 * 92 * @param key the name of the value to put 93 * @param value the data for the value to put 94 */ put(String key, String value)95 public void put(String key, String value) { 96 mValues.put(key, value); 97 } 98 99 /** 100 * Adds all values from the passed in ContentValues. 101 * 102 * @param other the ContentValues from which to copy 103 */ putAll(ContentValues other)104 public void putAll(ContentValues other) { 105 mValues.putAll(other.mValues); 106 } 107 108 /** 109 * Adds a value to the set. 110 * 111 * @param key the name of the value to put 112 * @param value the data for the value to put 113 */ put(String key, Byte value)114 public void put(String key, Byte value) { 115 mValues.put(key, value); 116 } 117 118 /** 119 * Adds a value to the set. 120 * 121 * @param key the name of the value to put 122 * @param value the data for the value to put 123 */ put(String key, Short value)124 public void put(String key, Short value) { 125 mValues.put(key, value); 126 } 127 128 /** 129 * Adds a value to the set. 130 * 131 * @param key the name of the value to put 132 * @param value the data for the value to put 133 */ put(String key, Integer value)134 public void put(String key, Integer value) { 135 mValues.put(key, value); 136 } 137 138 /** 139 * Adds a value to the set. 140 * 141 * @param key the name of the value to put 142 * @param value the data for the value to put 143 */ put(String key, Long value)144 public void put(String key, Long value) { 145 mValues.put(key, value); 146 } 147 148 /** 149 * Adds a value to the set. 150 * 151 * @param key the name of the value to put 152 * @param value the data for the value to put 153 */ put(String key, Float value)154 public void put(String key, Float value) { 155 mValues.put(key, value); 156 } 157 158 /** 159 * Adds a value to the set. 160 * 161 * @param key the name of the value to put 162 * @param value the data for the value to put 163 */ put(String key, Double value)164 public void put(String key, Double value) { 165 mValues.put(key, value); 166 } 167 168 /** 169 * Adds a value to the set. 170 * 171 * @param key the name of the value to put 172 * @param value the data for the value to put 173 */ put(String key, Boolean value)174 public void put(String key, Boolean value) { 175 mValues.put(key, value); 176 } 177 178 /** 179 * Adds a value to the set. 180 * 181 * @param key the name of the value to put 182 * @param value the data for the value to put 183 */ put(String key, byte[] value)184 public void put(String key, byte[] value) { 185 mValues.put(key, value); 186 } 187 188 /** 189 * Adds a null value to the set. 190 * 191 * @param key the name of the value to make null 192 */ putNull(String key)193 public void putNull(String key) { 194 mValues.put(key, null); 195 } 196 197 /** 198 * Returns the number of values. 199 * 200 * @return the number of values 201 */ size()202 public int size() { 203 return mValues.size(); 204 } 205 206 /** 207 * Indicates whether this collection is empty. 208 * 209 * @return true iff size == 0 210 * {@hide} 211 * TODO: consider exposing this new method publicly 212 */ isEmpty()213 public boolean isEmpty() { 214 return mValues.isEmpty(); 215 } 216 217 /** 218 * Remove a single value. 219 * 220 * @param key the name of the value to remove 221 */ remove(String key)222 public void remove(String key) { 223 mValues.remove(key); 224 } 225 226 /** 227 * Removes all values. 228 */ clear()229 public void clear() { 230 mValues.clear(); 231 } 232 233 /** 234 * Returns true if this object has the named value. 235 * 236 * @param key the value to check for 237 * @return {@code true} if the value is present, {@code false} otherwise 238 */ containsKey(String key)239 public boolean containsKey(String key) { 240 return mValues.containsKey(key); 241 } 242 243 /** 244 * Gets a value. Valid value types are {@link String}, {@link Boolean}, 245 * {@link Number}, and {@code byte[]} implementations. 246 * 247 * @param key the value to get 248 * @return the data for the value, or {@code null} if the value is missing or if {@code null} 249 * was previously added with the given {@code key} 250 */ get(String key)251 public Object get(String key) { 252 return mValues.get(key); 253 } 254 255 /** 256 * Gets a value and converts it to a String. 257 * 258 * @param key the value to get 259 * @return the String for the value 260 */ getAsString(String key)261 public String getAsString(String key) { 262 Object value = mValues.get(key); 263 return value != null ? value.toString() : null; 264 } 265 266 /** 267 * Gets a value and converts it to a Long. 268 * 269 * @param key the value to get 270 * @return the Long value, or {@code null} if the value is missing or cannot be converted 271 */ getAsLong(String key)272 public Long getAsLong(String key) { 273 Object value = mValues.get(key); 274 try { 275 return value != null ? ((Number) value).longValue() : null; 276 } catch (ClassCastException e) { 277 if (value instanceof CharSequence) { 278 try { 279 return Long.valueOf(value.toString()); 280 } catch (NumberFormatException e2) { 281 Log.e(TAG, "Cannot parse Long value for " + value + " at key " + key); 282 return null; 283 } 284 } else { 285 Log.e(TAG, "Cannot cast value for " + key + " to a Long: " + value, e); 286 return null; 287 } 288 } 289 } 290 291 /** 292 * Gets a value and converts it to an Integer. 293 * 294 * @param key the value to get 295 * @return the Integer value, or {@code null} if the value is missing or cannot be converted 296 */ getAsInteger(String key)297 public Integer getAsInteger(String key) { 298 Object value = mValues.get(key); 299 try { 300 return value != null ? ((Number) value).intValue() : null; 301 } catch (ClassCastException e) { 302 if (value instanceof CharSequence) { 303 try { 304 return Integer.valueOf(value.toString()); 305 } catch (NumberFormatException e2) { 306 Log.e(TAG, "Cannot parse Integer value for " + value + " at key " + key); 307 return null; 308 } 309 } else { 310 Log.e(TAG, "Cannot cast value for " + key + " to a Integer: " + value, e); 311 return null; 312 } 313 } 314 } 315 316 /** 317 * Gets a value and converts it to a Short. 318 * 319 * @param key the value to get 320 * @return the Short value, or {@code null} if the value is missing or cannot be converted 321 */ getAsShort(String key)322 public Short getAsShort(String key) { 323 Object value = mValues.get(key); 324 try { 325 return value != null ? ((Number) value).shortValue() : null; 326 } catch (ClassCastException e) { 327 if (value instanceof CharSequence) { 328 try { 329 return Short.valueOf(value.toString()); 330 } catch (NumberFormatException e2) { 331 Log.e(TAG, "Cannot parse Short value for " + value + " at key " + key); 332 return null; 333 } 334 } else { 335 Log.e(TAG, "Cannot cast value for " + key + " to a Short: " + value, e); 336 return null; 337 } 338 } 339 } 340 341 /** 342 * Gets a value and converts it to a Byte. 343 * 344 * @param key the value to get 345 * @return the Byte value, or {@code null} if the value is missing or cannot be converted 346 */ getAsByte(String key)347 public Byte getAsByte(String key) { 348 Object value = mValues.get(key); 349 try { 350 return value != null ? ((Number) value).byteValue() : null; 351 } catch (ClassCastException e) { 352 if (value instanceof CharSequence) { 353 try { 354 return Byte.valueOf(value.toString()); 355 } catch (NumberFormatException e2) { 356 Log.e(TAG, "Cannot parse Byte value for " + value + " at key " + key); 357 return null; 358 } 359 } else { 360 Log.e(TAG, "Cannot cast value for " + key + " to a Byte: " + value, e); 361 return null; 362 } 363 } 364 } 365 366 /** 367 * Gets a value and converts it to a Double. 368 * 369 * @param key the value to get 370 * @return the Double value, or {@code null} if the value is missing or cannot be converted 371 */ getAsDouble(String key)372 public Double getAsDouble(String key) { 373 Object value = mValues.get(key); 374 try { 375 return value != null ? ((Number) value).doubleValue() : null; 376 } catch (ClassCastException e) { 377 if (value instanceof CharSequence) { 378 try { 379 return Double.valueOf(value.toString()); 380 } catch (NumberFormatException e2) { 381 Log.e(TAG, "Cannot parse Double value for " + value + " at key " + key); 382 return null; 383 } 384 } else { 385 Log.e(TAG, "Cannot cast value for " + key + " to a Double: " + value, e); 386 return null; 387 } 388 } 389 } 390 391 /** 392 * Gets a value and converts it to a Float. 393 * 394 * @param key the value to get 395 * @return the Float value, or {@code null} if the value is missing or cannot be converted 396 */ getAsFloat(String key)397 public Float getAsFloat(String key) { 398 Object value = mValues.get(key); 399 try { 400 return value != null ? ((Number) value).floatValue() : null; 401 } catch (ClassCastException e) { 402 if (value instanceof CharSequence) { 403 try { 404 return Float.valueOf(value.toString()); 405 } catch (NumberFormatException e2) { 406 Log.e(TAG, "Cannot parse Float value for " + value + " at key " + key); 407 return null; 408 } 409 } else { 410 Log.e(TAG, "Cannot cast value for " + key + " to a Float: " + value, e); 411 return null; 412 } 413 } 414 } 415 416 /** 417 * Gets a value and converts it to a Boolean. 418 * 419 * @param key the value to get 420 * @return the Boolean value, or {@code null} if the value is missing or cannot be converted 421 */ getAsBoolean(String key)422 public Boolean getAsBoolean(String key) { 423 Object value = mValues.get(key); 424 try { 425 return (Boolean) value; 426 } catch (ClassCastException e) { 427 if (value instanceof CharSequence) { 428 // Note that we also check against 1 here because SQLite's internal representation 429 // for booleans is an integer with a value of 0 or 1. Without this check, boolean 430 // values obtained via DatabaseUtils#cursorRowToContentValues will always return 431 // false. 432 return Boolean.valueOf(value.toString()) || "1".equals(value); 433 } else if (value instanceof Number) { 434 return ((Number) value).intValue() != 0; 435 } else { 436 Log.e(TAG, "Cannot cast value for " + key + " to a Boolean: " + value, e); 437 return null; 438 } 439 } 440 } 441 442 /** 443 * Gets a value that is a byte array. Note that this method will not convert 444 * any other types to byte arrays. 445 * 446 * @param key the value to get 447 * @return the {@code byte[]} value, or {@code null} is the value is missing or not a 448 * {@code byte[]} 449 */ getAsByteArray(String key)450 public byte[] getAsByteArray(String key) { 451 Object value = mValues.get(key); 452 if (value instanceof byte[]) { 453 return (byte[]) value; 454 } else { 455 return null; 456 } 457 } 458 459 /** 460 * Returns a set of all of the keys and values 461 * 462 * @return a set of all of the keys and values 463 */ valueSet()464 public Set<Map.Entry<String, Object>> valueSet() { 465 return mValues.entrySet(); 466 } 467 468 /** 469 * Returns a set of all of the keys 470 * 471 * @return a set of all of the keys 472 */ keySet()473 public Set<String> keySet() { 474 return mValues.keySet(); 475 } 476 477 public static final Parcelable.Creator<ContentValues> CREATOR = 478 new Parcelable.Creator<ContentValues>() { 479 @SuppressWarnings({"deprecation", "unchecked"}) 480 public ContentValues createFromParcel(Parcel in) { 481 // TODO - what ClassLoader should be passed to readHashMap? 482 HashMap<String, Object> values = in.readHashMap(null); 483 return new ContentValues(values); 484 } 485 486 public ContentValues[] newArray(int size) { 487 return new ContentValues[size]; 488 } 489 }; 490 describeContents()491 public int describeContents() { 492 return 0; 493 } 494 495 @SuppressWarnings("deprecation") writeToParcel(Parcel parcel, int flags)496 public void writeToParcel(Parcel parcel, int flags) { 497 parcel.writeMap(mValues); 498 } 499 500 /** 501 * Unsupported, here until we get proper bulk insert APIs. 502 * {@hide} 503 */ 504 @Deprecated putStringArrayList(String key, ArrayList<String> value)505 public void putStringArrayList(String key, ArrayList<String> value) { 506 mValues.put(key, value); 507 } 508 509 /** 510 * Unsupported, here until we get proper bulk insert APIs. 511 * {@hide} 512 */ 513 @SuppressWarnings("unchecked") 514 @Deprecated getStringArrayList(String key)515 public ArrayList<String> getStringArrayList(String key) { 516 return (ArrayList<String>) mValues.get(key); 517 } 518 519 /** 520 * Returns a string containing a concise, human-readable description of this object. 521 * @return a printable representation of this object. 522 */ 523 @Override toString()524 public String toString() { 525 StringBuilder sb = new StringBuilder(); 526 for (String name : mValues.keySet()) { 527 String value = getAsString(name); 528 if (sb.length() > 0) sb.append(" "); 529 sb.append(name + "=" + value); 530 } 531 return sb.toString(); 532 } 533 } 534