• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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 package com.android.tools.metalava.apilevels;
17 
18 import java.io.PrintStream;
19 import java.util.Collection;
20 import java.util.HashMap;
21 import java.util.Map;
22 
23 /**
24  * Represents the whole Android API.
25  */
26 public class Api extends ApiElement {
27     private final Map<String, ApiClass> mClasses = new HashMap<>();
28     private final int mMax;
29 
Api(int max)30     public Api(int max) {
31         // Pretend that API started from version 0 to make sure that classes existed in the first version
32         // are printed with since="1".
33         super("Android API");
34         mMax = max;
35     }
36 
37     /**
38      * Prints the whole API definition to a stream.
39      *
40      * @param stream the stream to print the XML elements to
41      */
print(PrintStream stream)42     public void print(PrintStream stream) {
43         stream.println("<api version=\"2\">");
44         print(mClasses.values(), "class", "\t", stream);
45         printClosingTag("api", "", stream);
46     }
47 
48     /**
49      * Adds or updates a class.
50      *
51      * @param name       the name of the class
52      * @param version    an API version in which the class existed
53      * @param deprecated whether the class was deprecated in the API version
54      * @return the newly created or a previously existed class
55      */
addClass(String name, int version, boolean deprecated)56     public ApiClass addClass(String name, int version, boolean deprecated) {
57         ApiClass classElement = mClasses.get(name);
58         if (classElement == null) {
59             classElement = new ApiClass(name, version, deprecated);
60             mClasses.put(name, classElement);
61         } else {
62             classElement.update(version, deprecated);
63         }
64         return classElement;
65     }
66 
findClass(String name)67     public ApiClass findClass(String name) {
68         if (name == null) {
69             return null;
70         }
71         return mClasses.get(name);
72     }
73 
74     /**
75      * The bytecode visitor registers interfaces listed for a class. However,
76      * a class will <b>also</b> implement interfaces implemented by the super classes.
77      * This isn't available in the class file, so after all classes have been read in,
78      * we iterate through all classes, and for those that have interfaces, we check up
79      * the inheritance chain to see if it has already been introduced in a super class
80      * at an earlier API level.
81      */
removeImplicitInterfaces()82     public void removeImplicitInterfaces() {
83         for (ApiClass classElement : mClasses.values()) {
84             classElement.removeImplicitInterfaces(mClasses);
85         }
86     }
87 
88     /**
89      * @see ApiClass#removeOverridingMethods
90      */
removeOverridingMethods()91     public void removeOverridingMethods() {
92         for (ApiClass classElement : mClasses.values()) {
93             classElement.removeOverridingMethods(mClasses);
94         }
95     }
96 
inlineFromHiddenSuperClasses()97     public void inlineFromHiddenSuperClasses() {
98         Map<String, ApiClass> hidden = new HashMap<>();
99         for (ApiClass classElement : mClasses.values()) {
100             if (classElement.getHiddenUntil() < 0) { // hidden in the .jar files? (mMax==codebase, -1: jar files)
101                 hidden.put(classElement.getName(), classElement);
102             }
103         }
104         for (ApiClass classElement : mClasses.values()) {
105             classElement.inlineFromHiddenSuperClasses(hidden);
106         }
107     }
108 
prunePackagePrivateClasses()109     public void prunePackagePrivateClasses() {
110         for (ApiClass cls : mClasses.values()) {
111             cls.removeHiddenSuperClasses(mClasses);
112         }
113     }
114 }
115