--- /dev/null 2015-04-06 08:40:03.942185037 -0400 +++ new/test/runtime/SelectionResolution/HierarchyShape.java 2015-04-17 16:07:53.448392311 -0400 @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.NoSuchElementException; +import java.util.Set; +import java.util.Map; + +/** + * A representation of a class/interface hierarchy graph (just the + * graph; the class data is represented elsewhere). + */ +public class HierarchyShape { + public static final int OBJECT_CLASS = -1; + + protected int maxId; + + /** + * The names of all the classes. + */ + private final HashSet classes; + + /** + * The names of all the interfaces. + */ + private final HashSet interfaces; + private final HashMap> extensions; + + /** + * Create an empty hierarchy shape. + */ + public HierarchyShape() { + this(0, new HashSet<>(), new HashSet<>(), new HashMap<>()); + } + + private HierarchyShape(final int maxId, + final HashSet classes, + final HashSet interfaces, + final HashMap> extensions) { + this.maxId = maxId; + this.classes = classes; + this.interfaces = interfaces; + this.extensions = extensions; + } + + /** + * Make a copy of this hierarchy shape. + */ + public HierarchyShape copy() { + final HashMap> newextensions = new HashMap<>(); + + for(final Map.Entry> entry : + extensions.entrySet()) { + newextensions.put(entry.getKey(), + (HashSet)entry.getValue().clone()); + } + + return new HierarchyShape(maxId, (HashSet) classes.clone(), + (HashSet) interfaces.clone(), + newextensions); + } + + /** + * Add a class, and return its id. + * + * @return The new class id. + */ + public int addClass() { + final int id = maxId++; + classes.add(id); + return id; + } + + /** + * Add an interface, and return its id. + * + * @return The new interface id. + */ + public int addInterface() { + final int id = maxId++; + interfaces.add(id); + return id; + } + + /** + * Add an inheritance. + * + * @param sub The sub class/interface. + * @param sup The super class/interface + */ + public void addInherit(final int sub, + final int sup) { + HashSet ext = extensions.get(sub); + + if (ext == null) { + ext = new HashSet<>(); + extensions.put(sub, ext); + } + + ext.add(sup); + } + + @Override + public String toString() { + String out = ""; + for(int i = maxId - 1; i >= 0; i--) { + out += i + ": "; + for(int j = 0; j < maxId; j++) { + out += "[" + (inherits(i, j) ? "1" : "0") + "]"; + } + out += "\n"; + } + return out; + } + + /** + * Indicate whether the first class inherits from the second. + * + * @param sub The possible subtype. + * @param sup The possible supertype. + * @return Whether or not {@code sub} inherits from {@code sup}. + */ + public boolean inherits(final int sub, final int sup) { + final Set ext = extensions.get(sub); + if (ext != null) { + return ext.contains(sup); + } else { + return false; + } + } + + /** + * Indicate whether a given type name is a class. + * + * @param id The type in question. + * @return Whether or not the type is a class. + */ + public boolean isClass(final int id) { + if (id == OBJECT_CLASS) return true; + return classes.contains(id); + } + + /** + * Indicate whether a given type name is an interface. + * + * @param id The type in question. + * @return Whether or not the type is an interface. + */ + public boolean isInterface(final int id) { + if (id == OBJECT_CLASS) return false; + return interfaces.contains(id); + } + + /** + * Get an iterator over the classes. + * + * @return An iterator over classes. + */ + public Collection classes() { + return classes; + } + + /** + * Get an iterator over the interfaces. + * + * @return An iterator over interfaces. + */ + public Collection interfaces() { + return interfaces; + } + + /** + * Get an iterator over all types. + * + * @return An iterator over all types. + */ + public Collection types() { + final Set combined = new HashSet(classes); + combined.addAll(interfaces); + return combined; + } + + public int numClasses() { + return classes.size(); + } + + public int numInterfaces() { + return interfaces.size(); + } + + public int numTypes() { + return numClasses() + numInterfaces(); + } + +}