blob: 2752f3a9ab1a693d3a0b5a8f24c9930ed8733717 [file] [log] [blame]
Ben Dodson920dbbb2010-08-04 15:21:06 -07001/*
2 * Copyright (C) 2010 Google Inc.
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.google.doclava.apicheck;
18
19import com.google.doclava.ClassInfo;
20import com.google.doclava.Errors;
21import com.google.doclava.PackageInfo;
22import java.util.ArrayList;
C. Sean Young91c627c2015-05-11 15:36:03 -050023import java.util.Collection;
Ben Dodson920dbbb2010-08-04 15:21:06 -070024import java.util.HashMap;
25import java.util.Map;
26
27public class ApiInfo {
28
29 private HashMap<String, PackageInfo> mPackages
30 = new HashMap<String, PackageInfo>();
31 private HashMap<String, ClassInfo> mAllClasses
32 = new HashMap<String, ClassInfo>();
33 private Map<ClassInfo,String> mClassToSuper
34 = new HashMap<ClassInfo, String>();
35 private Map<ClassInfo, ArrayList<String>> mClassToInterface
36 = new HashMap<ClassInfo, ArrayList<String>>();
37
38
39 public ClassInfo findClass(String name) {
40 return mAllClasses.get(name);
41 }
42
43 protected void resolveInterfaces() {
44 for (ClassInfo cl : mAllClasses.values()) {
45 ArrayList<String> ifaces = mClassToInterface.get(cl);
46 if (ifaces == null) {
47 continue;
48 }
49 for (String iface : ifaces) {
Florian Uunk53d13be2014-06-25 17:01:21 +010050 ClassInfo ci = mAllClasses.get(iface);
51 if (ci == null) {
52 // Interface not provided by this codebase. Inject a stub.
53 ci = new ClassInfo(iface);
54 }
55 cl.addInterface(ci);
Ben Dodson920dbbb2010-08-04 15:21:06 -070056 }
57 }
58 }
59
60 /**
61 * Checks to see if this api is consistent with a newer version.
C. Sean Young91c627c2015-05-11 15:36:03 -050062 *
63 * @param otherApi the other api to test consistency against
64 * @param ignoredPackages packages to skip consistency checks (will match by exact name)
65 * @param ignoredClasses classes to skip consistency checks (will match by exact fully qualified
66 * name)
Ben Dodson920dbbb2010-08-04 15:21:06 -070067 */
C. Sean Young91c627c2015-05-11 15:36:03 -050068 public boolean isConsistent(ApiInfo otherApi,
69 Collection<String> ignoredPackages, Collection<String> ignoredClasses) {
Ben Dodson920dbbb2010-08-04 15:21:06 -070070 boolean consistent = true;
71 for (PackageInfo pInfo : mPackages.values()) {
C. Sean Young91c627c2015-05-11 15:36:03 -050072 // TODO: Add support for matching subpackages (e.g, something like
73 // test.example.* should match test.example.subpackage, and
74 // test.example.** should match the above AND test.example.subpackage.more)
75 if (ignoredPackages != null && ignoredPackages.contains(pInfo.name())) {
76 // TODO: Log skipping this?
77 continue;
78 }
Ben Dodson920dbbb2010-08-04 15:21:06 -070079 if (otherApi.getPackages().containsKey(pInfo.name())) {
C. Sean Young91c627c2015-05-11 15:36:03 -050080 if (!pInfo.isConsistent(otherApi.getPackages().get(pInfo.name()), ignoredClasses)) {
Ben Dodson920dbbb2010-08-04 15:21:06 -070081 consistent = false;
82 }
83 } else {
84 Errors.error(Errors.REMOVED_PACKAGE, pInfo.position(), "Removed package " + pInfo.name());
85 consistent = false;
86 }
87 }
88 for (PackageInfo pInfo : otherApi.mPackages.values()) {
C. Sean Young91c627c2015-05-11 15:36:03 -050089 if (ignoredPackages != null && ignoredPackages.contains(pInfo.name())) {
90 // TODO: Log skipping this?
91 continue;
92 }
Ben Dodson920dbbb2010-08-04 15:21:06 -070093 if (!mPackages.containsKey(pInfo.name())) {
94 Errors.error(Errors.ADDED_PACKAGE, pInfo.position(), "Added package " + pInfo.name());
95 consistent = false;
96 }
97 }
98 return consistent;
99 }
100
C. Sean Young91c627c2015-05-11 15:36:03 -0500101 /**
102 * Checks to see if this api is consistent with a newer version.
103 */
104 public boolean isConsistent(ApiInfo otherApi) {
105 return isConsistent(otherApi, null, null);
106 }
107
Ben Dodson920dbbb2010-08-04 15:21:06 -0700108 public HashMap<String, PackageInfo> getPackages() {
109 return mPackages;
110 }
Florian Uunk53d13be2014-06-25 17:01:21 +0100111
Ben Dodson920dbbb2010-08-04 15:21:06 -0700112 protected void mapClassToSuper(ClassInfo classInfo, String superclass) {
113 mClassToSuper.put(classInfo, superclass);
114 }
Florian Uunk53d13be2014-06-25 17:01:21 +0100115
Ben Dodson920dbbb2010-08-04 15:21:06 -0700116 protected void mapClassToInterface(ClassInfo classInfo, String iface) {
117 if (!mClassToInterface.containsKey(classInfo)) {
118 mClassToInterface.put(classInfo, new ArrayList<String>());
119 }
120 mClassToInterface.get(classInfo).add(iface);
121 }
122
123 protected void addPackage(PackageInfo pInfo) {
124 // track the set of organized packages in the API
Mathieu11b17962013-06-07 17:24:18 -0500125 pInfo.setContainingApi(this);
Ben Dodson920dbbb2010-08-04 15:21:06 -0700126 mPackages.put(pInfo.name(), pInfo);
127
128 // accumulate a direct map of all the classes in the API
129 for (ClassInfo cl : pInfo.allClasses().values()) {
130 mAllClasses.put(cl.qualifiedName(), cl);
131 }
132 }
133
134 protected void resolveSuperclasses() {
135 for (ClassInfo cl : mAllClasses.values()) {
136 // java.lang.Object has no superclass
137 if (!cl.qualifiedName().equals("java.lang.Object")) {
138 String scName = mClassToSuper.get(cl);
139 if (scName == null) {
140 scName = "java.lang.Object";
141 }
142 ClassInfo superclass = mAllClasses.get(scName);
143 if (superclass == null) {
144 // Superclass not provided by this codebase. Inject a stub.
145 superclass = new ClassInfo(scName);
146 }
147 cl.setSuperClass(superclass);
148 }
149 }
150 }
151}