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