BridgeXmlBlockParser.java revision 2fae858db55fc6984ef923a6226b9408c37c72cb
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 com.android.layoutlib.bridge.android;
18
19
20import com.android.ide.common.rendering.api.ILayoutPullParser;
21
22import org.xmlpull.v1.XmlPullParser;
23import org.xmlpull.v1.XmlPullParserException;
24
25import android.content.res.XmlResourceParser;
26import android.util.AttributeSet;
27import android.util.XmlPullAttributes;
28
29import java.io.IOException;
30import java.io.InputStream;
31import java.io.Reader;
32
33/**
34 * {@link BridgeXmlBlockParser} reimplements most of android.xml.XmlBlock.Parser.
35 * It delegates to both an instance of {@link XmlPullParser} and an instance of
36 * {@link XmlPullAttributes} (for the {@link AttributeSet} part).
37 */
38public class BridgeXmlBlockParser implements XmlResourceParser {
39
40    private final XmlPullParser mParser;
41    private final XmlPullAttributes mAttrib;
42    private final BridgeContext mContext;
43    private final boolean mPlatformFile;
44
45    private boolean mStarted = false;
46    private int mEventType = START_DOCUMENT;
47
48    private boolean mPopped = true; // default to true in case it's not pushed.
49
50    /**
51     * Builds a {@link BridgeXmlBlockParser}.
52     * @param parser The XmlPullParser to get the content from.
53     * @param context the Context.
54     * @param platformFile Indicates whether the the file is a platform file or not.
55     */
56    public BridgeXmlBlockParser(XmlPullParser parser, BridgeContext context, boolean platformFile) {
57        mParser = parser;
58        mContext = context;
59        mPlatformFile = platformFile;
60        mAttrib = new BridgeXmlPullAttributes(parser, context, mPlatformFile);
61
62        if (mContext != null) {
63            mContext.pushParser(this);
64            mPopped = false;
65        }
66    }
67
68    public boolean isPlatformFile() {
69        return mPlatformFile;
70    }
71
72    public Object getViewCookie() {
73        if (mParser instanceof ILayoutPullParser) {
74            return ((ILayoutPullParser)mParser).getViewCookie();
75        }
76
77        return null;
78    }
79
80    public void ensurePopped() {
81        if (mContext != null && mPopped == false) {
82            mContext.popParser();
83            mPopped = true;
84        }
85    }
86
87    // ------- XmlResourceParser implementation
88
89    public void setFeature(String name, boolean state)
90            throws XmlPullParserException {
91        if (FEATURE_PROCESS_NAMESPACES.equals(name) && state) {
92            return;
93        }
94        if (FEATURE_REPORT_NAMESPACE_ATTRIBUTES.equals(name) && state) {
95            return;
96        }
97        throw new XmlPullParserException("Unsupported feature: " + name);
98    }
99
100    public boolean getFeature(String name) {
101        if (FEATURE_PROCESS_NAMESPACES.equals(name)) {
102            return true;
103        }
104        if (FEATURE_REPORT_NAMESPACE_ATTRIBUTES.equals(name)) {
105            return true;
106        }
107        return false;
108    }
109
110    public void setProperty(String name, Object value) throws XmlPullParserException {
111        throw new XmlPullParserException("setProperty() not supported");
112    }
113
114    public Object getProperty(String name) {
115        return null;
116    }
117
118    public void setInput(Reader in) throws XmlPullParserException {
119        mParser.setInput(in);
120    }
121
122    public void setInput(InputStream inputStream, String inputEncoding)
123            throws XmlPullParserException {
124        mParser.setInput(inputStream, inputEncoding);
125    }
126
127    public void defineEntityReplacementText(String entityName,
128            String replacementText) throws XmlPullParserException {
129        throw new XmlPullParserException(
130                "defineEntityReplacementText() not supported");
131    }
132
133    public String getNamespacePrefix(int pos) throws XmlPullParserException {
134        throw new XmlPullParserException("getNamespacePrefix() not supported");
135    }
136
137    public String getInputEncoding() {
138        return null;
139    }
140
141    public String getNamespace(String prefix) {
142        throw new RuntimeException("getNamespace() not supported");
143    }
144
145    public int getNamespaceCount(int depth) throws XmlPullParserException {
146        throw new XmlPullParserException("getNamespaceCount() not supported");
147    }
148
149    public String getPositionDescription() {
150        return "Binary XML file line #" + getLineNumber();
151    }
152
153    public String getNamespaceUri(int pos) throws XmlPullParserException {
154        throw new XmlPullParserException("getNamespaceUri() not supported");
155    }
156
157    public int getColumnNumber() {
158        return -1;
159    }
160
161    public int getDepth() {
162        return mParser.getDepth();
163    }
164
165    public String getText() {
166        return mParser.getText();
167    }
168
169    public int getLineNumber() {
170        return mParser.getLineNumber();
171    }
172
173    public int getEventType() {
174        return mEventType;
175    }
176
177    public boolean isWhitespace() throws XmlPullParserException {
178        // Original comment: whitespace was stripped by aapt.
179        return mParser.isWhitespace();
180    }
181
182    public String getPrefix() {
183        throw new RuntimeException("getPrefix not supported");
184    }
185
186    public char[] getTextCharacters(int[] holderForStartAndLength) {
187        String txt = getText();
188        char[] chars = null;
189        if (txt != null) {
190            holderForStartAndLength[0] = 0;
191            holderForStartAndLength[1] = txt.length();
192            chars = new char[txt.length()];
193            txt.getChars(0, txt.length(), chars, 0);
194        }
195        return chars;
196    }
197
198    public String getNamespace() {
199        return mParser.getNamespace();
200    }
201
202    public String getName() {
203        return mParser.getName();
204    }
205
206    public String getAttributeNamespace(int index) {
207        return mParser.getAttributeNamespace(index);
208    }
209
210    public String getAttributeName(int index) {
211        return mParser.getAttributeName(index);
212    }
213
214    public String getAttributePrefix(int index) {
215        throw new RuntimeException("getAttributePrefix not supported");
216    }
217
218    public boolean isEmptyElementTag() {
219        // XXX Need to detect this.
220        return false;
221    }
222
223    public int getAttributeCount() {
224        return mParser.getAttributeCount();
225    }
226
227    public String getAttributeValue(int index) {
228        return mParser.getAttributeValue(index);
229    }
230
231    public String getAttributeType(int index) {
232        return "CDATA";
233    }
234
235    public boolean isAttributeDefault(int index) {
236        return false;
237    }
238
239    public int nextToken() throws XmlPullParserException, IOException {
240        return next();
241    }
242
243    public String getAttributeValue(String namespace, String name) {
244        return mParser.getAttributeValue(namespace, name);
245    }
246
247    public int next() throws XmlPullParserException, IOException {
248        if (!mStarted) {
249            mStarted = true;
250            return START_DOCUMENT;
251        }
252        int ev = mParser.next();
253
254        if (ev == END_TAG && mParser.getDepth() == 1) {
255            // done with parser remove it from the context stack.
256            ensurePopped();
257        }
258        mEventType = ev;
259        return ev;
260    }
261
262    public void require(int type, String namespace, String name)
263            throws XmlPullParserException {
264        if (type != getEventType()
265                || (namespace != null && !namespace.equals(getNamespace()))
266                || (name != null && !name.equals(getName())))
267            throw new XmlPullParserException("expected " + TYPES[type]
268                    + getPositionDescription());
269    }
270
271    public String nextText() throws XmlPullParserException, IOException {
272        if (getEventType() != START_TAG) {
273            throw new XmlPullParserException(getPositionDescription()
274                    + ": parser must be on START_TAG to read next text", this,
275                    null);
276        }
277        int eventType = next();
278        if (eventType == TEXT) {
279            String result = getText();
280            eventType = next();
281            if (eventType != END_TAG) {
282                throw new XmlPullParserException(
283                        getPositionDescription()
284                                + ": event TEXT it must be immediately followed by END_TAG",
285                        this, null);
286            }
287            return result;
288        } else if (eventType == END_TAG) {
289            return "";
290        } else {
291            throw new XmlPullParserException(getPositionDescription()
292                    + ": parser must be on START_TAG or TEXT to read text",
293                    this, null);
294        }
295    }
296
297    public int nextTag() throws XmlPullParserException, IOException {
298        int eventType = next();
299        if (eventType == TEXT && isWhitespace()) { // skip whitespace
300            eventType = next();
301        }
302        if (eventType != START_TAG && eventType != END_TAG) {
303            throw new XmlPullParserException(getPositionDescription()
304                    + ": expected start or end tag", this, null);
305        }
306        return eventType;
307    }
308
309    // AttributeSet implementation
310
311
312    public void close() {
313        // pass
314    }
315
316    public boolean getAttributeBooleanValue(int index, boolean defaultValue) {
317        return mAttrib.getAttributeBooleanValue(index, defaultValue);
318    }
319
320    public boolean getAttributeBooleanValue(String namespace, String attribute,
321            boolean defaultValue) {
322        return mAttrib.getAttributeBooleanValue(namespace, attribute, defaultValue);
323    }
324
325    public float getAttributeFloatValue(int index, float defaultValue) {
326        return mAttrib.getAttributeFloatValue(index, defaultValue);
327    }
328
329    public float getAttributeFloatValue(String namespace, String attribute, float defaultValue) {
330        return mAttrib.getAttributeFloatValue(namespace, attribute, defaultValue);
331    }
332
333    public int getAttributeIntValue(int index, int defaultValue) {
334        return mAttrib.getAttributeIntValue(index, defaultValue);
335    }
336
337    public int getAttributeIntValue(String namespace, String attribute, int defaultValue) {
338        return mAttrib.getAttributeIntValue(namespace, attribute, defaultValue);
339    }
340
341    public int getAttributeListValue(int index, String[] options, int defaultValue) {
342        return mAttrib.getAttributeListValue(index, options, defaultValue);
343    }
344
345    public int getAttributeListValue(String namespace, String attribute,
346            String[] options, int defaultValue) {
347        return mAttrib.getAttributeListValue(namespace, attribute, options, defaultValue);
348    }
349
350    public int getAttributeNameResource(int index) {
351        return mAttrib.getAttributeNameResource(index);
352    }
353
354    public int getAttributeResourceValue(int index, int defaultValue) {
355        return mAttrib.getAttributeResourceValue(index, defaultValue);
356    }
357
358    public int getAttributeResourceValue(String namespace, String attribute, int defaultValue) {
359        return mAttrib.getAttributeResourceValue(namespace, attribute, defaultValue);
360    }
361
362    public int getAttributeUnsignedIntValue(int index, int defaultValue) {
363        return mAttrib.getAttributeUnsignedIntValue(index, defaultValue);
364    }
365
366    public int getAttributeUnsignedIntValue(String namespace, String attribute, int defaultValue) {
367        return mAttrib.getAttributeUnsignedIntValue(namespace, attribute, defaultValue);
368    }
369
370    public String getClassAttribute() {
371        return mAttrib.getClassAttribute();
372    }
373
374    public String getIdAttribute() {
375        return mAttrib.getIdAttribute();
376    }
377
378    public int getIdAttributeResourceValue(int defaultValue) {
379        return mAttrib.getIdAttributeResourceValue(defaultValue);
380    }
381
382    public int getStyleAttribute() {
383        return mAttrib.getStyleAttribute();
384    }
385}
386