BridgeXmlBlockParser.java revision 02d2b5a4031c80bfe1012ce2f4f7b3695762abd9
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 ILayoutPullParser getParser(String layoutName) {
73        if (mParser instanceof ILayoutPullParser) {
74            return ((ILayoutPullParser)mParser).getParser(layoutName);
75        }
76
77        return null;
78    }
79
80    public Object getViewCookie() {
81        if (mParser instanceof ILayoutPullParser) {
82            return ((ILayoutPullParser)mParser).getViewCookie();
83        }
84
85        return null;
86    }
87
88    public void ensurePopped() {
89        if (mContext != null && mPopped == false) {
90            mContext.popParser();
91            mPopped = true;
92        }
93    }
94
95    // ------- XmlResourceParser implementation
96
97    public void setFeature(String name, boolean state)
98            throws XmlPullParserException {
99        if (FEATURE_PROCESS_NAMESPACES.equals(name) && state) {
100            return;
101        }
102        if (FEATURE_REPORT_NAMESPACE_ATTRIBUTES.equals(name) && state) {
103            return;
104        }
105        throw new XmlPullParserException("Unsupported feature: " + name);
106    }
107
108    public boolean getFeature(String name) {
109        if (FEATURE_PROCESS_NAMESPACES.equals(name)) {
110            return true;
111        }
112        if (FEATURE_REPORT_NAMESPACE_ATTRIBUTES.equals(name)) {
113            return true;
114        }
115        return false;
116    }
117
118    public void setProperty(String name, Object value) throws XmlPullParserException {
119        throw new XmlPullParserException("setProperty() not supported");
120    }
121
122    public Object getProperty(String name) {
123        return null;
124    }
125
126    public void setInput(Reader in) throws XmlPullParserException {
127        mParser.setInput(in);
128    }
129
130    public void setInput(InputStream inputStream, String inputEncoding)
131            throws XmlPullParserException {
132        mParser.setInput(inputStream, inputEncoding);
133    }
134
135    public void defineEntityReplacementText(String entityName,
136            String replacementText) throws XmlPullParserException {
137        throw new XmlPullParserException(
138                "defineEntityReplacementText() not supported");
139    }
140
141    public String getNamespacePrefix(int pos) throws XmlPullParserException {
142        throw new XmlPullParserException("getNamespacePrefix() not supported");
143    }
144
145    public String getInputEncoding() {
146        return null;
147    }
148
149    public String getNamespace(String prefix) {
150        throw new RuntimeException("getNamespace() not supported");
151    }
152
153    public int getNamespaceCount(int depth) throws XmlPullParserException {
154        throw new XmlPullParserException("getNamespaceCount() not supported");
155    }
156
157    public String getPositionDescription() {
158        return "Binary XML file line #" + getLineNumber();
159    }
160
161    public String getNamespaceUri(int pos) throws XmlPullParserException {
162        throw new XmlPullParserException("getNamespaceUri() not supported");
163    }
164
165    public int getColumnNumber() {
166        return -1;
167    }
168
169    public int getDepth() {
170        return mParser.getDepth();
171    }
172
173    public String getText() {
174        return mParser.getText();
175    }
176
177    public int getLineNumber() {
178        return mParser.getLineNumber();
179    }
180
181    public int getEventType() {
182        return mEventType;
183    }
184
185    public boolean isWhitespace() throws XmlPullParserException {
186        // Original comment: whitespace was stripped by aapt.
187        return mParser.isWhitespace();
188    }
189
190    public String getPrefix() {
191        throw new RuntimeException("getPrefix not supported");
192    }
193
194    public char[] getTextCharacters(int[] holderForStartAndLength) {
195        String txt = getText();
196        char[] chars = null;
197        if (txt != null) {
198            holderForStartAndLength[0] = 0;
199            holderForStartAndLength[1] = txt.length();
200            chars = new char[txt.length()];
201            txt.getChars(0, txt.length(), chars, 0);
202        }
203        return chars;
204    }
205
206    public String getNamespace() {
207        return mParser.getNamespace();
208    }
209
210    public String getName() {
211        return mParser.getName();
212    }
213
214    public String getAttributeNamespace(int index) {
215        return mParser.getAttributeNamespace(index);
216    }
217
218    public String getAttributeName(int index) {
219        return mParser.getAttributeName(index);
220    }
221
222    public String getAttributePrefix(int index) {
223        throw new RuntimeException("getAttributePrefix not supported");
224    }
225
226    public boolean isEmptyElementTag() {
227        // XXX Need to detect this.
228        return false;
229    }
230
231    public int getAttributeCount() {
232        return mParser.getAttributeCount();
233    }
234
235    public String getAttributeValue(int index) {
236        return mParser.getAttributeValue(index);
237    }
238
239    public String getAttributeType(int index) {
240        return "CDATA";
241    }
242
243    public boolean isAttributeDefault(int index) {
244        return false;
245    }
246
247    public int nextToken() throws XmlPullParserException, IOException {
248        return next();
249    }
250
251    public String getAttributeValue(String namespace, String name) {
252        return mParser.getAttributeValue(namespace, name);
253    }
254
255    public int next() throws XmlPullParserException, IOException {
256        if (!mStarted) {
257            mStarted = true;
258            return START_DOCUMENT;
259        }
260        int ev = mParser.next();
261
262        if (ev == END_TAG && mParser.getDepth() == 1) {
263            // done with parser remove it from the context stack.
264            ensurePopped();
265        }
266        mEventType = ev;
267        return ev;
268    }
269
270    public void require(int type, String namespace, String name)
271            throws XmlPullParserException {
272        if (type != getEventType()
273                || (namespace != null && !namespace.equals(getNamespace()))
274                || (name != null && !name.equals(getName())))
275            throw new XmlPullParserException("expected " + TYPES[type]
276                    + getPositionDescription());
277    }
278
279    public String nextText() throws XmlPullParserException, IOException {
280        if (getEventType() != START_TAG) {
281            throw new XmlPullParserException(getPositionDescription()
282                    + ": parser must be on START_TAG to read next text", this,
283                    null);
284        }
285        int eventType = next();
286        if (eventType == TEXT) {
287            String result = getText();
288            eventType = next();
289            if (eventType != END_TAG) {
290                throw new XmlPullParserException(
291                        getPositionDescription()
292                                + ": event TEXT it must be immediately followed by END_TAG",
293                        this, null);
294            }
295            return result;
296        } else if (eventType == END_TAG) {
297            return "";
298        } else {
299            throw new XmlPullParserException(getPositionDescription()
300                    + ": parser must be on START_TAG or TEXT to read text",
301                    this, null);
302        }
303    }
304
305    public int nextTag() throws XmlPullParserException, IOException {
306        int eventType = next();
307        if (eventType == TEXT && isWhitespace()) { // skip whitespace
308            eventType = next();
309        }
310        if (eventType != START_TAG && eventType != END_TAG) {
311            throw new XmlPullParserException(getPositionDescription()
312                    + ": expected start or end tag", this, null);
313        }
314        return eventType;
315    }
316
317    // AttributeSet implementation
318
319
320    public void close() {
321        // pass
322    }
323
324    public boolean getAttributeBooleanValue(int index, boolean defaultValue) {
325        return mAttrib.getAttributeBooleanValue(index, defaultValue);
326    }
327
328    public boolean getAttributeBooleanValue(String namespace, String attribute,
329            boolean defaultValue) {
330        return mAttrib.getAttributeBooleanValue(namespace, attribute, defaultValue);
331    }
332
333    public float getAttributeFloatValue(int index, float defaultValue) {
334        return mAttrib.getAttributeFloatValue(index, defaultValue);
335    }
336
337    public float getAttributeFloatValue(String namespace, String attribute, float defaultValue) {
338        return mAttrib.getAttributeFloatValue(namespace, attribute, defaultValue);
339    }
340
341    public int getAttributeIntValue(int index, int defaultValue) {
342        return mAttrib.getAttributeIntValue(index, defaultValue);
343    }
344
345    public int getAttributeIntValue(String namespace, String attribute, int defaultValue) {
346        return mAttrib.getAttributeIntValue(namespace, attribute, defaultValue);
347    }
348
349    public int getAttributeListValue(int index, String[] options, int defaultValue) {
350        return mAttrib.getAttributeListValue(index, options, defaultValue);
351    }
352
353    public int getAttributeListValue(String namespace, String attribute,
354            String[] options, int defaultValue) {
355        return mAttrib.getAttributeListValue(namespace, attribute, options, defaultValue);
356    }
357
358    public int getAttributeNameResource(int index) {
359        return mAttrib.getAttributeNameResource(index);
360    }
361
362    public int getAttributeResourceValue(int index, int defaultValue) {
363        return mAttrib.getAttributeResourceValue(index, defaultValue);
364    }
365
366    public int getAttributeResourceValue(String namespace, String attribute, int defaultValue) {
367        return mAttrib.getAttributeResourceValue(namespace, attribute, defaultValue);
368    }
369
370    public int getAttributeUnsignedIntValue(int index, int defaultValue) {
371        return mAttrib.getAttributeUnsignedIntValue(index, defaultValue);
372    }
373
374    public int getAttributeUnsignedIntValue(String namespace, String attribute, int defaultValue) {
375        return mAttrib.getAttributeUnsignedIntValue(namespace, attribute, defaultValue);
376    }
377
378    public String getClassAttribute() {
379        return mAttrib.getClassAttribute();
380    }
381
382    public String getIdAttribute() {
383        return mAttrib.getIdAttribute();
384    }
385
386    public int getIdAttributeResourceValue(int defaultValue) {
387        return mAttrib.getIdAttributeResourceValue(defaultValue);
388    }
389
390    public int getStyleAttribute() {
391        return mAttrib.getStyleAttribute();
392    }
393}
394