1/* 2 * Copyright (c) 2012, 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 24package org.openjdk.tests.shapegen; 25 26import java.util.ArrayList; 27import java.util.HashSet; 28import java.util.List; 29import java.util.Map; 30import java.util.Set; 31 32/** 33 * 34 * @author Robert Field 35 */ 36public class ClassCase { 37 38 public enum Kind { 39 IVAC (true, "v"), 40 IPRESENT (true, "p"), 41 IDEFAULT (true, "d"), 42 CNONE (false, "n"), 43 CABSTRACT (false, "a"), 44 CCONCRETE (false, "c"); 45 46 private final String prefix; 47 public final boolean isInterface; 48 49 Kind(boolean isInterface, String prefix) { 50 this.isInterface = isInterface; 51 this.prefix = prefix; 52 } 53 54 public String getPrefix() { return prefix; } 55 } 56 57 public final Kind kind; 58 private final ClassCase superclass; 59 private final List<ClassCase> supertypes; 60 61 private String name; 62 private boolean _OK; 63 private boolean _HasClassMethod; 64 private Set<ClassCase> _mprov; 65 private boolean _IsConcrete; 66 private boolean _HasDefault; 67 private ClassCase _mres; 68 private ClassCase _mdefend; 69 70 private Set<RuleGroup> executed = new HashSet<RuleGroup>(); 71 72 public ClassCase(Kind kind, ClassCase superclass, List<ClassCase> interfaces) { 73 this.kind = kind; 74 this.superclass = superclass; 75 76 // Set supertypes from superclass (if any) and interfaces 77 List<ClassCase> lc; 78 if (superclass == null) { 79 lc = interfaces; 80 } else { 81 lc = new ArrayList<>(); 82 lc.add(superclass); 83 lc.addAll(interfaces); 84 } 85 this.supertypes = lc; 86 } 87 88 public final boolean isInterface() { return kind.isInterface; } 89 public final boolean isClass() { return !kind.isInterface; } 90 91 public Set<ClassCase> get_mprov() { 92 exec(RuleGroup.PROVENENCE); 93 return _mprov; 94 } 95 96 public void set_mprov(ClassCase cc) { 97 Set<ClassCase> s = new HashSet<>(); 98 s.add(cc); 99 _mprov = s; 100 } 101 102 public void set_mprov(Set<ClassCase> s) { 103 _mprov = s; 104 } 105 106 public ClassCase get_mres() { 107 exec(RuleGroup.RESOLUTION); 108 return _mres; 109 } 110 111 public void set_mres(ClassCase cc) { 112 _mres = cc; 113 } 114 115 public ClassCase get_mdefend() { 116 exec(RuleGroup.DEFENDER); 117 return _mdefend; 118 } 119 120 public void set_mdefend(ClassCase cc) { 121 _mdefend = cc; 122 } 123 124 public boolean get_HasClassMethod() { 125 exec(RuleGroup.PROVENENCE); 126 return _HasClassMethod; 127 } 128 129 public void set_HasClassMethod(boolean bool) { 130 _HasClassMethod = bool; 131 } 132 133 public boolean get_HasDefault() { 134 exec(RuleGroup.MARKER); 135 return _HasDefault; 136 } 137 138 public void set_HasDefault(boolean bool) { 139 _HasDefault = bool; 140 } 141 142 public boolean get_IsConcrete() { 143 exec(RuleGroup.MARKER); 144 return _IsConcrete; 145 } 146 147 public void set_IsConcrete(boolean bool) { 148 _IsConcrete = bool; 149 } 150 151 public boolean get_OK() { 152 exec(RuleGroup.CHECKING); 153 return _OK; 154 } 155 156 public void set_OK(boolean bool) { 157 _OK = bool; 158 } 159 160 public boolean isMethodDefined() { 161 for (ClassCase cc : supertypes) { 162 if (cc.isMethodDefined()) { 163 return true; 164 } 165 } 166 switch (kind) { 167 case CCONCRETE: 168 case CABSTRACT: 169 case IPRESENT: 170 case IDEFAULT: 171 return true; 172 default: 173 return false; 174 } 175 } 176 177 public boolean isAbstract() { 178 return isMethodDefined() && (get_mres()==null); 179 } 180 181 public boolean hasSuperclass() { 182 return superclass != null; 183 } 184 185 public ClassCase getSuperclass() { 186 return superclass; 187 } 188 189 public List<ClassCase> getSupertypes() { 190 return supertypes; 191 } 192 193 public List<ClassCase> getInterfaces() { 194 if (superclass != null) { 195 if (supertypes.get(0) != superclass) { 196 throw new AssertionError("superclass missing from supertypes"); 197 } 198 return supertypes.subList(1, supertypes.size()); 199 } else { 200 return supertypes; 201 } 202 } 203 204 public boolean isSubtypeOf(ClassCase cc) { 205 // S-Refl 206 if (cc.equals(this)) { 207 return true; 208 } 209 210 // S-Def 211 for (ClassCase sp : getSupertypes()) { 212 if (cc.equals(sp)) { 213 return true; 214 } 215 } 216 217 // _S-Trans 218 for (ClassCase sp : getSupertypes()) { 219 if (sp.isSubtypeOf(cc)) { 220 return true; 221 } 222 } 223 224 return false; 225 } 226 227 public void init(Map<String, Integer> namingContext) { 228 if (name != null) { 229 return; // Already inited 230 } 231 232 for (ClassCase sup : supertypes) { 233 sup.init(namingContext); 234 } 235 236 // Build name 237 StringBuilder sb = new StringBuilder(); 238 if (!supertypes.isEmpty()) { 239 sb.append(isInterface() ? "I" : "C"); 240 for (ClassCase cc : supertypes) { 241 sb.append(cc.getName()); 242 } 243 sb.append(kind.isInterface ? "i" : "c"); 244 } 245 sb.append(kind.prefix); 246 String pname = sb.toString(); 247 Integer icnt = namingContext.get(pname); 248 int cnt = icnt == null ? 0 : icnt; 249 ++cnt; 250 namingContext.put(pname, cnt); 251 if (cnt > 1) { 252 sb.append(cnt); 253 } 254 this.name = sb.toString(); 255 } 256 257 public boolean isa(Kind... kinds) { 258 for (Kind k : kinds) { 259 if (kind == k) { 260 return true; 261 } 262 } 263 return false; 264 } 265 266 private void exec(RuleGroup rg ) { 267 if (!executed.contains(rg)) { 268 rg.exec(this); 269 executed.add(rg); 270 } 271 } 272 273 public void collectClasses(Set<ClassCase> seen) { 274 seen.add(this); 275 for (ClassCase cc : supertypes) { 276 cc.collectClasses(seen); 277 } 278 } 279 280 public String getID() { 281 if (name == null) { 282 throw new Error("Access to uninitialized ClassCase"); 283 } else { 284 return name; 285 } 286 } 287 288 public final String getName() { 289 if (name == null) { 290 return "ClassCase uninited@" + hashCode(); 291 } else { 292 return name; 293 } 294 } 295 296 @Override 297 public boolean equals(Object obj) { 298 return obj instanceof ClassCase && getID().equals(((ClassCase)obj).getID()); 299 } 300 301 @Override 302 public int hashCode() { 303 return getID().hashCode(); 304 } 305 306 @Override 307 public String toString() { 308 return getName(); 309 } 310} 311