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