1/*
2 * Copyright (C) 2008 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 android.util;
18
19import com.android.ide.common.rendering.api.RenderResources;
20import com.android.ide.common.rendering.api.ResourceValue;
21import com.android.internal.util.XmlUtils;
22import com.android.layoutlib.bridge.Bridge;
23import com.android.layoutlib.bridge.BridgeConstants;
24import com.android.layoutlib.bridge.android.BridgeContext;
25import com.android.layoutlib.bridge.impl.ResourceHelper;
26import com.android.resources.ResourceType;
27
28import org.xmlpull.v1.XmlPullParser;
29
30/**
31 * A correct implementation of the {@link AttributeSet} interface on top of a XmlPullParser
32 */
33public class BridgeXmlPullAttributes extends XmlPullAttributes {
34
35    private final BridgeContext mContext;
36    private final boolean mPlatformFile;
37
38    public BridgeXmlPullAttributes(XmlPullParser parser, BridgeContext context,
39            boolean platformFile) {
40        super(parser);
41        mContext = context;
42        mPlatformFile = platformFile;
43    }
44
45    /*
46     * (non-Javadoc)
47     * @see android.util.XmlPullAttributes#getAttributeNameResource(int)
48     *
49     * This methods must return com.android.internal.R.attr.<name> matching
50     * the name of the attribute.
51     * It returns 0 if it doesn't find anything.
52     */
53    @Override
54    public int getAttributeNameResource(int index) {
55        // get the attribute name.
56        String name = getAttributeName(index);
57
58        // get the attribute namespace
59        String ns = mParser.getAttributeNamespace(index);
60
61        if (BridgeConstants.NS_RESOURCES.equals(ns)) {
62            Integer v = Bridge.getResourceId(ResourceType.ATTR, name);
63            if (v != null) {
64                return v.intValue();
65            }
66
67            return 0;
68        }
69
70        // this is not an attribute in the android namespace, we query the customviewloader, if
71        // the namespaces match.
72        if (mContext.getLayoutlibCallback().getNamespace().equals(ns)) {
73            Integer v = mContext.getLayoutlibCallback().getResourceId(ResourceType.ATTR, name);
74            if (v != null) {
75                return v.intValue();
76            }
77        }
78
79        return 0;
80    }
81
82    @Override
83    public int getAttributeListValue(String namespace, String attribute,
84            String[] options, int defaultValue) {
85        String value = getAttributeValue(namespace, attribute);
86        if (value != null) {
87            ResourceValue r = getResourceValue(value);
88
89            if (r != null) {
90                value = r.getValue();
91            }
92
93            return XmlUtils.convertValueToList(value, options, defaultValue);
94        }
95
96        return defaultValue;
97    }
98
99    @Override
100    public boolean getAttributeBooleanValue(String namespace, String attribute,
101            boolean defaultValue) {
102        String value = getAttributeValue(namespace, attribute);
103        if (value != null) {
104            ResourceValue r = getResourceValue(value);
105
106            if (r != null) {
107                value = r.getValue();
108            }
109
110            return XmlUtils.convertValueToBoolean(value, defaultValue);
111        }
112
113        return defaultValue;
114    }
115
116    @Override
117    public int getAttributeResourceValue(String namespace, String attribute, int defaultValue) {
118        String value = getAttributeValue(namespace, attribute);
119
120        return resolveResourceValue(value, defaultValue);
121    }
122
123    @Override
124    public int getAttributeIntValue(String namespace, String attribute,
125            int defaultValue) {
126        String value = getAttributeValue(namespace, attribute);
127        if (value != null) {
128            ResourceValue r = getResourceValue(value);
129
130            if (r != null) {
131                value = r.getValue();
132            }
133
134            return XmlUtils.convertValueToInt(value, defaultValue);
135        }
136
137        return defaultValue;
138    }
139
140    @Override
141    public int getAttributeUnsignedIntValue(String namespace, String attribute,
142            int defaultValue) {
143        String value = getAttributeValue(namespace, attribute);
144        if (value != null) {
145            ResourceValue r = getResourceValue(value);
146
147            if (r != null) {
148                value = r.getValue();
149            }
150
151            return XmlUtils.convertValueToUnsignedInt(value, defaultValue);
152        }
153
154        return defaultValue;
155    }
156
157    @Override
158    public float getAttributeFloatValue(String namespace, String attribute,
159            float defaultValue) {
160        String s = getAttributeValue(namespace, attribute);
161        if (s != null) {
162            ResourceValue r = getResourceValue(s);
163
164            if (r != null) {
165                s = r.getValue();
166            }
167
168            return Float.parseFloat(s);
169        }
170
171        return defaultValue;
172    }
173
174    @Override
175    public int getAttributeListValue(int index,
176            String[] options, int defaultValue) {
177        return XmlUtils.convertValueToList(
178            getAttributeValue(index), options, defaultValue);
179    }
180
181    @Override
182    public boolean getAttributeBooleanValue(int index, boolean defaultValue) {
183        String value = getAttributeValue(index);
184        if (value != null) {
185            ResourceValue r = getResourceValue(value);
186
187            if (r != null) {
188                value = r.getValue();
189            }
190
191            return XmlUtils.convertValueToBoolean(value, defaultValue);
192        }
193
194        return defaultValue;
195    }
196
197    @Override
198    public int getAttributeResourceValue(int index, int defaultValue) {
199        String value = getAttributeValue(index);
200
201        return resolveResourceValue(value, defaultValue);
202    }
203
204    @Override
205    public int getAttributeIntValue(int index, int defaultValue) {
206        String value = getAttributeValue(index);
207        if (value != null) {
208            ResourceValue r = getResourceValue(value);
209
210            if (r != null) {
211                value = r.getValue();
212            }
213
214            if (value.charAt(0) == '#') {
215                return ResourceHelper.getColor(value);
216            }
217            return XmlUtils.convertValueToInt(value, defaultValue);
218        }
219
220        return defaultValue;
221    }
222
223    @Override
224    public int getAttributeUnsignedIntValue(int index, int defaultValue) {
225        String value = getAttributeValue(index);
226        if (value != null) {
227            ResourceValue r = getResourceValue(value);
228
229            if (r != null) {
230                value = r.getValue();
231            }
232
233            return XmlUtils.convertValueToUnsignedInt(value, defaultValue);
234        }
235
236        return defaultValue;
237    }
238
239    @Override
240    public float getAttributeFloatValue(int index, float defaultValue) {
241        String s = getAttributeValue(index);
242        if (s != null) {
243            ResourceValue r = getResourceValue(s);
244
245            if (r != null) {
246                s = r.getValue();
247            }
248
249            return Float.parseFloat(s);
250        }
251
252        return defaultValue;
253    }
254
255    // -- private helper methods
256
257    /**
258     * Returns a resolved {@link ResourceValue} from a given value.
259     */
260    private ResourceValue getResourceValue(String value) {
261        // now look for this particular value
262        RenderResources resources = mContext.getRenderResources();
263        return resources.resolveResValue(resources.findResValue(value, mPlatformFile));
264    }
265
266    /**
267     * Resolves and return a value to its associated integer.
268     */
269    private int resolveResourceValue(String value, int defaultValue) {
270        ResourceValue resource = getResourceValue(value);
271        if (resource != null) {
272            Integer id = null;
273            if (mPlatformFile || resource.isFramework()) {
274                id = Bridge.getResourceId(resource.getResourceType(), resource.getName());
275            } else {
276                id = mContext.getLayoutlibCallback().getResourceId(
277                        resource.getResourceType(), resource.getName());
278            }
279
280            if (id != null) {
281                return id;
282            }
283        }
284
285        return defaultValue;
286    }
287}
288