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