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