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