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