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      * Remove a single value.
208      *
209      * @param key the name of the value to remove
210      */
remove(String key)211     public void remove(String key) {
212         mValues.remove(key);
213     }
214 
215     /**
216      * Removes all values.
217      */
clear()218     public void clear() {
219         mValues.clear();
220     }
221 
222     /**
223      * Returns true if this object has the named value.
224      *
225      * @param key the value to check for
226      * @return {@code true} if the value is present, {@code false} otherwise
227      */
containsKey(String key)228     public boolean containsKey(String key) {
229         return mValues.containsKey(key);
230     }
231 
232     /**
233      * Gets a value. Valid value types are {@link String}, {@link Boolean}, and
234      * {@link Number} implementations.
235      *
236      * @param key the value to get
237      * @return the data for the value
238      */
get(String key)239     public Object get(String key) {
240         return mValues.get(key);
241     }
242 
243     /**
244      * Gets a value and converts it to a String.
245      *
246      * @param key the value to get
247      * @return the String for the value
248      */
getAsString(String key)249     public String getAsString(String key) {
250         Object value = mValues.get(key);
251         return value != null ? value.toString() : null;
252     }
253 
254     /**
255      * Gets a value and converts it to a Long.
256      *
257      * @param key the value to get
258      * @return the Long value, or null if the value is missing or cannot be converted
259      */
getAsLong(String key)260     public Long getAsLong(String key) {
261         Object value = mValues.get(key);
262         try {
263             return value != null ? ((Number) value).longValue() : null;
264         } catch (ClassCastException e) {
265             if (value instanceof CharSequence) {
266                 try {
267                     return Long.valueOf(value.toString());
268                 } catch (NumberFormatException e2) {
269                     Log.e(TAG, "Cannot parse Long value for " + value + " at key " + key);
270                     return null;
271                 }
272             } else {
273                 Log.e(TAG, "Cannot cast value for " + key + " to a Long: " + value, e);
274                 return null;
275             }
276         }
277     }
278 
279     /**
280      * Gets a value and converts it to an Integer.
281      *
282      * @param key the value to get
283      * @return the Integer value, or null if the value is missing or cannot be converted
284      */
getAsInteger(String key)285     public Integer getAsInteger(String key) {
286         Object value = mValues.get(key);
287         try {
288             return value != null ? ((Number) value).intValue() : null;
289         } catch (ClassCastException e) {
290             if (value instanceof CharSequence) {
291                 try {
292                     return Integer.valueOf(value.toString());
293                 } catch (NumberFormatException e2) {
294                     Log.e(TAG, "Cannot parse Integer value for " + value + " at key " + key);
295                     return null;
296                 }
297             } else {
298                 Log.e(TAG, "Cannot cast value for " + key + " to a Integer: " + value, e);
299                 return null;
300             }
301         }
302     }
303 
304     /**
305      * Gets a value and converts it to a Short.
306      *
307      * @param key the value to get
308      * @return the Short value, or null if the value is missing or cannot be converted
309      */
getAsShort(String key)310     public Short getAsShort(String key) {
311         Object value = mValues.get(key);
312         try {
313             return value != null ? ((Number) value).shortValue() : null;
314         } catch (ClassCastException e) {
315             if (value instanceof CharSequence) {
316                 try {
317                     return Short.valueOf(value.toString());
318                 } catch (NumberFormatException e2) {
319                     Log.e(TAG, "Cannot parse Short value for " + value + " at key " + key);
320                     return null;
321                 }
322             } else {
323                 Log.e(TAG, "Cannot cast value for " + key + " to a Short: " + value, e);
324                 return null;
325             }
326         }
327     }
328 
329     /**
330      * Gets a value and converts it to a Byte.
331      *
332      * @param key the value to get
333      * @return the Byte value, or null if the value is missing or cannot be converted
334      */
getAsByte(String key)335     public Byte getAsByte(String key) {
336         Object value = mValues.get(key);
337         try {
338             return value != null ? ((Number) value).byteValue() : null;
339         } catch (ClassCastException e) {
340             if (value instanceof CharSequence) {
341                 try {
342                     return Byte.valueOf(value.toString());
343                 } catch (NumberFormatException e2) {
344                     Log.e(TAG, "Cannot parse Byte value for " + value + " at key " + key);
345                     return null;
346                 }
347             } else {
348                 Log.e(TAG, "Cannot cast value for " + key + " to a Byte: " + value, e);
349                 return null;
350             }
351         }
352     }
353 
354     /**
355      * Gets a value and converts it to a Double.
356      *
357      * @param key the value to get
358      * @return the Double value, or null if the value is missing or cannot be converted
359      */
getAsDouble(String key)360     public Double getAsDouble(String key) {
361         Object value = mValues.get(key);
362         try {
363             return value != null ? ((Number) value).doubleValue() : null;
364         } catch (ClassCastException e) {
365             if (value instanceof CharSequence) {
366                 try {
367                     return Double.valueOf(value.toString());
368                 } catch (NumberFormatException e2) {
369                     Log.e(TAG, "Cannot parse Double value for " + value + " at key " + key);
370                     return null;
371                 }
372             } else {
373                 Log.e(TAG, "Cannot cast value for " + key + " to a Double: " + value, e);
374                 return null;
375             }
376         }
377     }
378 
379     /**
380      * Gets a value and converts it to a Float.
381      *
382      * @param key the value to get
383      * @return the Float value, or null if the value is missing or cannot be converted
384      */
getAsFloat(String key)385     public Float getAsFloat(String key) {
386         Object value = mValues.get(key);
387         try {
388             return value != null ? ((Number) value).floatValue() : null;
389         } catch (ClassCastException e) {
390             if (value instanceof CharSequence) {
391                 try {
392                     return Float.valueOf(value.toString());
393                 } catch (NumberFormatException e2) {
394                     Log.e(TAG, "Cannot parse Float value for " + value + " at key " + key);
395                     return null;
396                 }
397             } else {
398                 Log.e(TAG, "Cannot cast value for " + key + " to a Float: " + value, e);
399                 return null;
400             }
401         }
402     }
403 
404     /**
405      * Gets a value and converts it to a Boolean.
406      *
407      * @param key the value to get
408      * @return the Boolean value, or null if the value is missing or cannot be converted
409      */
getAsBoolean(String key)410     public Boolean getAsBoolean(String key) {
411         Object value = mValues.get(key);
412         try {
413             return (Boolean) value;
414         } catch (ClassCastException e) {
415             if (value instanceof CharSequence) {
416                 return Boolean.valueOf(value.toString());
417             } else if (value instanceof Number) {
418                 return ((Number) value).intValue() != 0;
419             } else {
420                 Log.e(TAG, "Cannot cast value for " + key + " to a Boolean: " + value, e);
421                 return null;
422             }
423         }
424     }
425 
426     /**
427      * Gets a value that is a byte array. Note that this method will not convert
428      * any other types to byte arrays.
429      *
430      * @param key the value to get
431      * @return the byte[] value, or null is the value is missing or not a byte[]
432      */
getAsByteArray(String key)433     public byte[] getAsByteArray(String key) {
434         Object value = mValues.get(key);
435         if (value instanceof byte[]) {
436             return (byte[]) value;
437         } else {
438             return null;
439         }
440     }
441 
442     /**
443      * Returns a set of all of the keys and values
444      *
445      * @return a set of all of the keys and values
446      */
valueSet()447     public Set<Map.Entry<String, Object>> valueSet() {
448         return mValues.entrySet();
449     }
450 
451     /**
452      * Returns a set of all of the keys
453      *
454      * @return a set of all of the keys
455      */
keySet()456     public Set<String> keySet() {
457         return mValues.keySet();
458     }
459 
460     public static final Parcelable.Creator<ContentValues> CREATOR =
461             new Parcelable.Creator<ContentValues>() {
462         @SuppressWarnings({"deprecation", "unchecked"})
463         public ContentValues createFromParcel(Parcel in) {
464             // TODO - what ClassLoader should be passed to readHashMap?
465             HashMap<String, Object> values = in.readHashMap(null);
466             return new ContentValues(values);
467         }
468 
469         public ContentValues[] newArray(int size) {
470             return new ContentValues[size];
471         }
472     };
473 
describeContents()474     public int describeContents() {
475         return 0;
476     }
477 
478     @SuppressWarnings("deprecation")
writeToParcel(Parcel parcel, int flags)479     public void writeToParcel(Parcel parcel, int flags) {
480         parcel.writeMap(mValues);
481     }
482 
483     /**
484      * Unsupported, here until we get proper bulk insert APIs.
485      * {@hide}
486      */
487     @Deprecated
putStringArrayList(String key, ArrayList<String> value)488     public void putStringArrayList(String key, ArrayList<String> value) {
489         mValues.put(key, value);
490     }
491 
492     /**
493      * Unsupported, here until we get proper bulk insert APIs.
494      * {@hide}
495      */
496     @SuppressWarnings("unchecked")
497     @Deprecated
getStringArrayList(String key)498     public ArrayList<String> getStringArrayList(String key) {
499         return (ArrayList<String>) mValues.get(key);
500     }
501 
502     /**
503      * Returns a string containing a concise, human-readable description of this object.
504      * @return a printable representation of this object.
505      */
506     @Override
toString()507     public String toString() {
508         StringBuilder sb = new StringBuilder();
509         for (String name : mValues.keySet()) {
510             String value = getAsString(name);
511             if (sb.length() > 0) sb.append(" ");
512             sb.append(name + "=" + value);
513         }
514         return sb.toString();
515     }
516 }
517