1 /* 2 * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 package selectionresolution; 25 26 import java.util.Arrays; 27 import java.util.Collection; 28 import java.util.HashMap; 29 import java.util.HashSet; 30 import java.util.Set; 31 import java.util.Map; 32 33 /** 34 * A representation of a class/interface hierarchy graph (just the 35 * graph; the class data is represented elsewhere). 36 */ 37 public class HierarchyShape { 38 public static final int OBJECT_CLASS = -1; 39 40 protected int maxId; 41 42 /** 43 * The names of all the classes. 44 */ 45 private final HashSet<Integer> classes; 46 47 /** 48 * The names of all the interfaces. 49 */ 50 private final HashSet<Integer> interfaces; 51 private final HashMap<Integer, HashSet<Integer>> extensions; 52 53 /** 54 * Create an empty hierarchy shape. 55 */ HierarchyShape()56 public HierarchyShape() { 57 this(0, new HashSet<>(), new HashSet<>(), new HashMap<>()); 58 } 59 HierarchyShape(final int maxId, final HashSet<Integer> classes, final HashSet<Integer> interfaces, final HashMap<Integer, HashSet<Integer>> extensions)60 private HierarchyShape(final int maxId, 61 final HashSet<Integer> classes, 62 final HashSet<Integer> interfaces, 63 final HashMap<Integer, HashSet<Integer>> extensions) { 64 this.maxId = maxId; 65 this.classes = classes; 66 this.interfaces = interfaces; 67 this.extensions = extensions; 68 } 69 70 /** 71 * Make a copy of this hierarchy shape. 72 */ copy()73 public HierarchyShape copy() { 74 final HashMap<Integer, HashSet<Integer>> newextensions = new HashMap<>(); 75 76 for(final Map.Entry<Integer, HashSet<Integer>> entry : 77 extensions.entrySet()) { 78 newextensions.put(entry.getKey(), 79 (HashSet<Integer>)entry.getValue().clone()); 80 } 81 82 return new HierarchyShape(maxId, (HashSet<Integer>) classes.clone(), 83 (HashSet<Integer>) interfaces.clone(), 84 newextensions); 85 } 86 87 /** 88 * Add a class, and return its id. 89 * 90 * @return The new class id. 91 */ addClass()92 public int addClass() { 93 final int id = maxId++; 94 classes.add(id); 95 return id; 96 } 97 98 /** 99 * Add an interface, and return its id. 100 * 101 * @return The new interface id. 102 */ addInterface()103 public int addInterface() { 104 final int id = maxId++; 105 interfaces.add(id); 106 return id; 107 } 108 109 /** 110 * Add an inheritance. 111 * 112 * @param sub The sub class/interface. 113 * @param sup The super class/interface 114 */ addInherit(final int sub, final int sup)115 public void addInherit(final int sub, 116 final int sup) { 117 HashSet<Integer> ext = extensions.get(sub); 118 119 if (ext == null) { 120 ext = new HashSet<>(); 121 extensions.put(sub, ext); 122 } 123 124 ext.add(sup); 125 } 126 127 @Override toString()128 public String toString() { 129 String out = ""; 130 for(int i = maxId - 1; i >= 0; i--) { 131 out += i + ": "; 132 for(int j = 0; j < maxId; j++) { 133 out += "[" + (inherits(i, j) ? "1" : "0") + "]"; 134 } 135 out += "\n"; 136 } 137 return out; 138 } 139 140 /** 141 * Indicate whether the first class inherits from the second. 142 * 143 * @param sub The possible subtype. 144 * @param sup The possible supertype. 145 * @return Whether or not {@code sub} inherits from {@code sup}. 146 */ inherits(final int sub, final int sup)147 public boolean inherits(final int sub, final int sup) { 148 final Set<Integer> ext = extensions.get(sub); 149 if (ext != null) { 150 return ext.contains(sup); 151 } else { 152 return false; 153 } 154 } 155 156 /** 157 * Indicate whether a given type name is a class. 158 * 159 * @param id The type in question. 160 * @return Whether or not the type is a class. 161 */ isClass(final int id)162 public boolean isClass(final int id) { 163 if (id == OBJECT_CLASS) { 164 return true; 165 } 166 return classes.contains(id); 167 } 168 169 /** 170 * Indicate whether a given type name is an interface. 171 * 172 * @param id The type in question. 173 * @return Whether or not the type is an interface. 174 */ isInterface(final int id)175 public boolean isInterface(final int id) { 176 if (id == OBJECT_CLASS) { 177 return false; 178 } 179 return interfaces.contains(id); 180 } 181 182 /** 183 * Get an iterator over the classes. 184 * 185 * @return An iterator over classes. 186 */ classes()187 public Collection<Integer> classes() { 188 return classes; 189 } 190 191 /** 192 * Get an iterator over the interfaces. 193 * 194 * @return An iterator over interfaces. 195 */ interfaces()196 public Collection<Integer> interfaces() { 197 return interfaces; 198 } 199 200 /** 201 * Get an iterator over all types. 202 * 203 * @return An iterator over all types. 204 */ types()205 public Collection<Integer> types() { 206 final Set<Integer> combined = new HashSet(classes); 207 combined.addAll(interfaces); 208 return combined; 209 } 210 numClasses()211 public int numClasses() { 212 return classes.size(); 213 } 214 numInterfaces()215 public int numInterfaces() { 216 return interfaces.size(); 217 } 218 numTypes()219 public int numTypes() { 220 return numClasses() + numInterfaces(); 221 } 222 223 } 224