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
17package com.xtremelabs.robolectric.shadows;
18
19import android.content.ContentValues;
20import android.util.Log;
21import com.xtremelabs.robolectric.internal.Implementation;
22import com.xtremelabs.robolectric.internal.Implements;
23
24import java.util.HashMap;
25import java.util.Map;
26import java.util.Set;
27
28import static com.xtremelabs.robolectric.Robolectric.shadowOf;
29import static com.xtremelabs.robolectric.Robolectric.shadowOf_;
30
31/**
32 * Shadows the {@code android.content.ContentValues} class.
33 * <p/>
34 * This is a fancy map from String to... something. Works just like the Android class it shadows.
35 */
36@SuppressWarnings({"UnusedDeclaration"})
37@Implements(ContentValues.class)
38public final class ShadowContentValues {
39    private static final String TAG = "ShadowContentValues";
40    private HashMap<String, Object> values = new HashMap<String, Object>();
41
42    public void __constructor__(ContentValues from) {
43        values = new HashMap<String, Object>(shadowOf(from).values);
44    }
45
46    @Implementation
47    public void put(String key, String value) {
48        values.put(key, value);
49    }
50
51    @Implementation
52    public void putAll(ContentValues other) {
53        values.putAll(shadowOf(other).values);
54    }
55
56    @Implementation
57    public void put(String key, Byte value) {
58        values.put(key, value);
59    }
60
61    @Implementation
62    public void put(String key, Short value) {
63        values.put(key, value);
64    }
65
66    @Implementation
67    public void put(String key, Integer value) {
68        values.put(key, value);
69    }
70
71    @Implementation
72    public void put(String key, Long value) {
73        values.put(key, value);
74    }
75
76    @Implementation
77    public void put(String key, Float value) {
78        values.put(key, value);
79    }
80
81    @Implementation
82    public void put(String key, Double value) {
83        values.put(key, value);
84    }
85
86    @Implementation
87    public void put(String key, Boolean value) {
88        values.put(key, value);
89    }
90
91    @Implementation
92    public void put(String key, byte[] value) {
93        values.put(key, value);
94    }
95
96    @Implementation
97    public void putNull(String key) {
98        values.put(key, null);
99    }
100
101    @Implementation
102    public int size() {
103        return values.size();
104    }
105
106    @Implementation
107    public void remove(String key) {
108        values.remove(key);
109    }
110
111    @Implementation
112    public void clear() {
113        values.clear();
114    }
115
116    @Implementation
117    public boolean containsKey(String key) {
118        return values.containsKey(key);
119    }
120
121    @Implementation
122    public Object get(String key) {
123        return values.get(key);
124    }
125
126    @Implementation
127    public String getAsString(String key) {
128        Object value = values.get(key);
129        return value != null ? value.toString() : null;
130    }
131
132    @Implementation
133    public Long getAsLong(String key) {
134        Object value = values.get(key);
135        try {
136            return value != null ? ((Number) value).longValue() : null;
137        } catch (ClassCastException e) {
138            if (value instanceof CharSequence) {
139                try {
140                    return Long.valueOf(value.toString());
141                } catch (NumberFormatException e2) {
142                    Log.e(TAG, "Cannot parse Long value for " + value + " at key " + key);
143                    return null;
144                }
145            } else {
146                Log.e(TAG, "Cannot cast value for " + key + " to a Long: " + value, e);
147                return null;
148            }
149        }
150    }
151
152    @Implementation
153    public Integer getAsInteger(String key) {
154        Object value = values.get(key);
155        try {
156            return value != null ? ((Number) value).intValue() : null;
157        } catch (ClassCastException e) {
158            if (value instanceof CharSequence) {
159                try {
160                    return Integer.valueOf(value.toString());
161                } catch (NumberFormatException e2) {
162                    Log.e(TAG, "Cannot parse Integer value for " + value + " at key " + key);
163                    return null;
164                }
165            } else {
166                Log.e(TAG, "Cannot cast value for " + key + " to a Integer: " + value, e);
167                return null;
168            }
169        }
170    }
171
172    @Implementation
173    public Short getAsShort(String key) {
174        Object value = values.get(key);
175        try {
176            return value != null ? ((Number) value).shortValue() : null;
177        } catch (ClassCastException e) {
178            if (value instanceof CharSequence) {
179                try {
180                    return Short.valueOf(value.toString());
181                } catch (NumberFormatException e2) {
182                    Log.e(TAG, "Cannot parse Short value for " + value + " at key " + key);
183                    return null;
184                }
185            } else {
186                Log.e(TAG, "Cannot cast value for " + key + " to a Short: " + value, e);
187                return null;
188            }
189        }
190    }
191
192    @Implementation
193    public Byte getAsByte(String key) {
194        Object value = values.get(key);
195        try {
196            return value != null ? ((Number) value).byteValue() : null;
197        } catch (ClassCastException e) {
198            if (value instanceof CharSequence) {
199                try {
200                    return Byte.valueOf(value.toString());
201                } catch (NumberFormatException e2) {
202                    Log.e(TAG, "Cannot parse Byte value for " + value + " at key " + key);
203                    return null;
204                }
205            } else {
206                Log.e(TAG, "Cannot cast value for " + key + " to a Byte: " + value, e);
207                return null;
208            }
209        }
210    }
211
212    @Implementation
213    public Double getAsDouble(String key) {
214        Object value = values.get(key);
215        try {
216            return value != null ? ((Number) value).doubleValue() : null;
217        } catch (ClassCastException e) {
218            if (value instanceof CharSequence) {
219                try {
220                    return Double.valueOf(value.toString());
221                } catch (NumberFormatException e2) {
222                    Log.e(TAG, "Cannot parse Double value for " + value + " at key " + key);
223                    return null;
224                }
225            } else {
226                Log.e(TAG, "Cannot cast value for " + key + " to a Double: " + value, e);
227                return null;
228            }
229        }
230    }
231
232    @Implementation
233    public Float getAsFloat(String key) {
234        Object value = values.get(key);
235        try {
236            return value != null ? ((Number) value).floatValue() : null;
237        } catch (ClassCastException e) {
238            if (value instanceof CharSequence) {
239                try {
240                    return Float.valueOf(value.toString());
241                } catch (NumberFormatException e2) {
242                    Log.e(TAG, "Cannot parse Float value for " + value + " at key " + key);
243                    return null;
244                }
245            } else {
246                Log.e(TAG, "Cannot cast value for " + key + " to a Float: " + value, e);
247                return null;
248            }
249        }
250    }
251
252    @Implementation
253    public Boolean getAsBoolean(String key) {
254        Object value = values.get(key);
255        try {
256            return (Boolean) value;
257        } catch (ClassCastException e) {
258            if (value instanceof CharSequence) {
259                return Boolean.valueOf(value.toString());
260            } else {
261                Log.e(TAG, "Cannot cast value for " + key + " to a Boolean: " + value, e);
262                return null;
263            }
264        }
265    }
266
267    @Implementation
268    public byte[] getAsByteArray(String key) {
269        Object value = values.get(key);
270        if (value instanceof byte[]) {
271            return (byte[]) value;
272        } else {
273            return null;
274        }
275    }
276
277    @Implementation
278    public Set<Map.Entry<String, Object>> valueSet() {
279        return values.entrySet();
280    }
281
282    @Implementation
283    public int describeContents() {
284        return 0;
285    }
286
287    @Override @Implementation
288    public boolean equals(Object object) {
289        if (object == null) return false;
290        Object o = shadowOf_(object);
291        if (o == null) return false;
292        if (this == o) return true;
293        if (getClass() != o.getClass()) return false;
294
295        if (!(o instanceof ContentValues)) {
296            return false;
297        }
298        return values.equals(shadowOf((ContentValues) o).values);
299    }
300
301    @Override @Implementation
302    public int hashCode() {
303        return values.hashCode();
304    }
305
306    @Override @Implementation
307    public String toString() {
308        StringBuilder sb = new StringBuilder();
309        for (String name : values.keySet()) {
310            String value = getAsString(name);
311            if (sb.length() > 0) sb.append(" ");
312            sb.append(name + "=" + value);
313        }
314        return sb.toString();
315    }
316}
317