1 /* 2 * Copyright (C) 2010 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.cts.apicoverage; 18 19 import org.xml.sax.Attributes; 20 import org.xml.sax.SAXException; 21 import org.xml.sax.helpers.DefaultHandler; 22 23 import java.util.ArrayList; 24 import java.util.List; 25 26 /** 27 * {@link DefaultHandler} that builds an empty {@link ApiCoverage} object from scanning current.xml. 28 */ 29 class CurrentXmlHandler extends DefaultHandler { 30 31 private String mCurrentPackageName; 32 33 private String mCurrentClassName; 34 35 private boolean mIgnoreCurrentClass; 36 37 private String mCurrentMethodName; 38 39 private String mCurrentMethodReturnType; 40 41 private boolean mCurrentMethodIsAbstract; 42 43 private String mCurrentMethodVisibility; 44 45 private boolean mCurrentMethodStaticMethod; 46 47 private boolean mCurrentMethodFinalMethod; 48 49 private boolean mDeprecated; 50 51 52 private List<String> mCurrentParameterTypes = new ArrayList<String>(); 53 54 private ApiCoverage mApiCoverage = new ApiCoverage(); 55 getApi()56 public ApiCoverage getApi() { 57 return mApiCoverage; 58 } 59 60 @Override startElement(String uri, String localName, String name, Attributes attributes)61 public void startElement(String uri, String localName, String name, Attributes attributes) 62 throws SAXException { 63 super.startElement(uri, localName, name, attributes); 64 if ("package".equalsIgnoreCase(localName)) { 65 mCurrentPackageName = getValue(attributes, "name"); 66 67 ApiPackage apiPackage = new ApiPackage(mCurrentPackageName); 68 mApiCoverage.addPackage(apiPackage); 69 70 } else if ("class".equalsIgnoreCase(localName)) { 71 if (isEnum(attributes)) { 72 mIgnoreCurrentClass = true; 73 return; 74 } 75 mIgnoreCurrentClass = false; 76 mCurrentClassName = getValue(attributes, "name"); 77 mDeprecated = isDeprecated(attributes); 78 String superClass = attributes.getValue("extends"); 79 ApiClass apiClass = new ApiClass( 80 mCurrentClassName, mDeprecated, is(attributes, "abstract"), superClass); 81 ApiPackage apiPackage = mApiCoverage.getPackage(mCurrentPackageName); 82 apiPackage.addClass(apiClass); 83 } else if ("interface".equalsIgnoreCase(localName)) { 84 // don't add interface 85 mIgnoreCurrentClass = true; 86 } else if ("constructor".equalsIgnoreCase(localName)) { 87 mDeprecated = isDeprecated(attributes); 88 mCurrentParameterTypes.clear(); 89 } else if ("method".equalsIgnoreCase(localName)) { 90 mDeprecated = isDeprecated(attributes); 91 mCurrentMethodName = getValue(attributes, "name"); 92 mCurrentMethodReturnType = getValue(attributes, "return"); 93 mCurrentMethodIsAbstract = is(attributes, "abstract"); 94 mCurrentMethodVisibility = getValue(attributes, "visibility"); 95 mCurrentMethodStaticMethod = is(attributes, "static"); 96 mCurrentMethodFinalMethod = is(attributes, "final"); 97 mCurrentParameterTypes.clear(); 98 } else if ("parameter".equalsIgnoreCase(localName)) { 99 mCurrentParameterTypes.add(getValue(attributes, "type")); 100 } 101 } 102 103 @Override endElement(String uri, String localName, String name)104 public void endElement(String uri, String localName, String name) throws SAXException { 105 super.endElement(uri, localName, name); 106 if (mIgnoreCurrentClass) { 107 // do not add anything for interface 108 return; 109 } 110 if ("constructor".equalsIgnoreCase(localName)) { 111 if (mCurrentParameterTypes.isEmpty()) { 112 // Don't add empty default constructors... 113 return; 114 } 115 ApiConstructor apiConstructor = new ApiConstructor(mCurrentClassName, 116 mCurrentParameterTypes, mDeprecated); 117 ApiPackage apiPackage = mApiCoverage.getPackage(mCurrentPackageName); 118 ApiClass apiClass = apiPackage.getClass(mCurrentClassName); 119 apiClass.addConstructor(apiConstructor); 120 } else if ("method".equalsIgnoreCase(localName)) { 121 ApiMethod apiMethod = new ApiMethod( 122 mCurrentMethodName, 123 mCurrentParameterTypes, 124 mCurrentMethodReturnType, 125 mDeprecated, 126 mCurrentMethodVisibility, 127 mCurrentMethodStaticMethod, 128 mCurrentMethodFinalMethod, 129 mCurrentMethodIsAbstract); 130 ApiPackage apiPackage = mApiCoverage.getPackage(mCurrentPackageName); 131 ApiClass apiClass = apiPackage.getClass(mCurrentClassName); 132 apiClass.addMethod(apiMethod); 133 } 134 } 135 getValue(Attributes attributes, String key)136 static String getValue(Attributes attributes, String key) { 137 // Strip away generics <...> and make inner classes always use a "." rather than "$". 138 return attributes.getValue(key) 139 .replaceAll("<.+>", "") 140 .replace("$", "."); 141 } 142 isDeprecated(Attributes attributes)143 private boolean isDeprecated(Attributes attributes) { 144 return "deprecated".equals(attributes.getValue("deprecated")); 145 } 146 is(Attributes attributes, String valueName)147 private static boolean is(Attributes attributes, String valueName) { 148 return "true".equals(attributes.getValue(valueName)); 149 } 150 isEnum(Attributes attributes)151 private boolean isEnum(Attributes attributes) { 152 return "java.lang.Enum".equals(attributes.getValue("extends")); 153 } 154 }