Home | History | Annotate | Download | only in content
      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      */
     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      */
     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      */
     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      */
     72     private ContentValues(HashMap<String, Object> values) {
     73         mValues = values;
     74     }
     75 
     76     @Override
     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
     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      */
     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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    222     public void remove(String key) {
    223         mValues.remove(key);
    224     }
    225 
    226     /**
    227      * Removes all values.
    228      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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 
    491     public int describeContents() {
    492         return 0;
    493     }
    494 
    495     @SuppressWarnings("deprecation")
    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
    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
    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
    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