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 }