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