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 java.util.Collection; 20 import java.util.Collections; 21 import java.util.HashMap; 22 import java.util.Iterator; 23 import java.util.Map; 24 import java.util.Map.Entry; 25 import java.util.concurrent.ConcurrentHashMap; 26 27 /** Representation of a package in the API containing classes. */ 28 class ApiPackage implements HasCoverage { 29 30 private final String mName; 31 32 private final Map<String, ApiClass> mApiClassMap = new ConcurrentHashMap<>(); 33 ApiPackage(String name)34 ApiPackage(String name) { 35 mName = name; 36 } 37 38 @Override getName()39 public String getName() { 40 return mName; 41 } 42 addClass(ApiClass apiClass)43 public void addClass(ApiClass apiClass) { 44 mApiClassMap.put(apiClass.getName(), apiClass); 45 } 46 getClass(String name)47 public ApiClass getClass(String name) { 48 return name == null ? null : mApiClassMap.get(name); 49 } 50 getClasses()51 public Collection<ApiClass> getClasses() { 52 return Collections.unmodifiableCollection(mApiClassMap.values()); 53 } 54 getNumCoveredMethods()55 public int getNumCoveredMethods() { 56 int covered = 0; 57 for (ApiClass apiClass : mApiClassMap.values()) { 58 covered += apiClass.getNumCoveredMethods(); 59 } 60 return covered; 61 } 62 getTotalMethods()63 public int getTotalMethods() { 64 int total = 0; 65 for (ApiClass apiClass : mApiClassMap.values()) { 66 total += apiClass.getTotalMethods(); 67 } 68 return total; 69 } 70 71 @Override getCoveragePercentage()72 public float getCoveragePercentage() { 73 return (float) getNumCoveredMethods() / getTotalMethods() * 100; 74 } 75 76 @Override getMemberSize()77 public int getMemberSize() { 78 return getTotalMethods(); 79 } 80 81 /** Iterate through all classes and add superclass. */ resolveSuperClasses(Map<String, ApiPackage> packageMap)82 public void resolveSuperClasses(Map<String, ApiPackage> packageMap) { 83 Iterator<Entry<String, ApiClass>> it = mApiClassMap.entrySet().iterator(); 84 while (it.hasNext()) { 85 Map.Entry<String, ApiClass> entry = it.next(); 86 ApiClass apiClass = entry.getValue(); 87 if (apiClass.getSuperClassName() != null) { 88 // Add the super class 89 String superClassName = apiClass.getSuperClassName(); 90 ApiClass superClass = findClass(packageMap, superClassName); 91 apiClass.setSuperClass(superClass); 92 } 93 for (String interfaceName : apiClass.getInterfaceNames()) { 94 // Add the interface 95 ApiClass apiInterface = findClass(packageMap, interfaceName); 96 apiClass.resolveInterface(interfaceName, apiInterface); 97 } 98 } 99 } 100 101 /** Find a class that matches the fully qualified class name. */ findClass(Map<String, ApiPackage> packageMap, String fullClassName)102 private ApiClass findClass(Map<String, ApiPackage> packageMap, String fullClassName) { 103 // Split the fully qualified class name into package and class name. 104 int delimiterIndex = fullClassName.lastIndexOf('.'); 105 while (delimiterIndex > 0) { 106 String packageName = fullClassName.substring(0, delimiterIndex); 107 String className = fullClassName.substring(delimiterIndex + 1); 108 if (packageMap.containsKey(packageName)) { 109 ApiPackage apiPackage = packageMap.get(packageName); 110 ApiClass apiClass = apiPackage.getClass(className); 111 if (apiClass != null) { 112 // api class found 113 return apiClass; 114 } 115 } 116 delimiterIndex = fullClassName.lastIndexOf('.', delimiterIndex - 1); 117 } 118 return null; 119 } 120 } 121 122