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