blob: 68421bf53ed148cd5853aa726864f4c1c05948c8 [file] [log] [blame]
/*
* Copyright (c) 2012, 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.
*/
package org.openjdk.tests.shapegen;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
*
* @author Robert Field
*/
public class ClassCase {
public enum Kind {
IVAC (true, "v"),
IPRESENT (true, "p"),
IDEFAULT (true, "d"),
CNONE (false, "n"),
CABSTRACT (false, "a"),
CCONCRETE (false, "c");
private final String prefix;
public final boolean isInterface;
Kind(boolean isInterface, String prefix) {
this.isInterface = isInterface;
this.prefix = prefix;
}
public String getPrefix() { return prefix; }
}
public final Kind kind;
private final ClassCase superclass;
private final List<ClassCase> supertypes;
private String name;
private boolean _OK;
private boolean _HasClassMethod;
private Set<ClassCase> _mprov;
private boolean _IsConcrete;
private boolean _HasDefault;
private ClassCase _mres;
private ClassCase _mdefend;
private Set<RuleGroup> executed = new HashSet<RuleGroup>();
public ClassCase(Kind kind, ClassCase superclass, List<ClassCase> interfaces) {
this.kind = kind;
this.superclass = superclass;
// Set supertypes from superclass (if any) and interfaces
List<ClassCase> lc;
if (superclass == null) {
lc = interfaces;
} else {
lc = new ArrayList<>();
lc.add(superclass);
lc.addAll(interfaces);
}
this.supertypes = lc;
}
public final boolean isInterface() { return kind.isInterface; }
public final boolean isClass() { return !kind.isInterface; }
public Set<ClassCase> get_mprov() {
exec(RuleGroup.PROVENENCE);
return _mprov;
}
public void set_mprov(ClassCase cc) {
Set<ClassCase> s = new HashSet<>();
s.add(cc);
_mprov = s;
}
public void set_mprov(Set<ClassCase> s) {
_mprov = s;
}
public ClassCase get_mres() {
exec(RuleGroup.RESOLUTION);
return _mres;
}
public void set_mres(ClassCase cc) {
_mres = cc;
}
public ClassCase get_mdefend() {
exec(RuleGroup.DEFENDER);
return _mdefend;
}
public void set_mdefend(ClassCase cc) {
_mdefend = cc;
}
public boolean get_HasClassMethod() {
exec(RuleGroup.PROVENENCE);
return _HasClassMethod;
}
public void set_HasClassMethod(boolean bool) {
_HasClassMethod = bool;
}
public boolean get_HasDefault() {
exec(RuleGroup.MARKER);
return _HasDefault;
}
public void set_HasDefault(boolean bool) {
_HasDefault = bool;
}
public boolean get_IsConcrete() {
exec(RuleGroup.MARKER);
return _IsConcrete;
}
public void set_IsConcrete(boolean bool) {
_IsConcrete = bool;
}
public boolean get_OK() {
exec(RuleGroup.CHECKING);
return _OK;
}
public void set_OK(boolean bool) {
_OK = bool;
}
public boolean isMethodDefined() {
for (ClassCase cc : supertypes) {
if (cc.isMethodDefined()) {
return true;
}
}
switch (kind) {
case CCONCRETE:
case CABSTRACT:
case IPRESENT:
case IDEFAULT:
return true;
default:
return false;
}
}
public boolean isAbstract() {
return isMethodDefined() && (get_mres()==null);
}
public boolean hasSuperclass() {
return superclass != null;
}
public ClassCase getSuperclass() {
return superclass;
}
public List<ClassCase> getSupertypes() {
return supertypes;
}
public List<ClassCase> getInterfaces() {
if (superclass != null) {
if (supertypes.get(0) != superclass) {
throw new AssertionError("superclass missing from supertypes");
}
return supertypes.subList(1, supertypes.size());
} else {
return supertypes;
}
}
public boolean isSubtypeOf(ClassCase cc) {
// S-Refl
if (cc.equals(this)) {
return true;
}
// S-Def
for (ClassCase sp : getSupertypes()) {
if (cc.equals(sp)) {
return true;
}
}
// _S-Trans
for (ClassCase sp : getSupertypes()) {
if (sp.isSubtypeOf(cc)) {
return true;
}
}
return false;
}
public void init(Map<String, Integer> namingContext) {
if (name != null) {
return; // Already inited
}
for (ClassCase sup : supertypes) {
sup.init(namingContext);
}
// Build name
StringBuilder sb = new StringBuilder();
if (!supertypes.isEmpty()) {
sb.append(isInterface() ? "I" : "C");
for (ClassCase cc : supertypes) {
sb.append(cc.getName());
}
sb.append(kind.isInterface ? "i" : "c");
}
sb.append(kind.prefix);
String pname = sb.toString();
Integer icnt = namingContext.get(pname);
int cnt = icnt == null ? 0 : icnt;
++cnt;
namingContext.put(pname, cnt);
if (cnt > 1) {
sb.append(cnt);
}
this.name = sb.toString();
}
public boolean isa(Kind... kinds) {
for (Kind k : kinds) {
if (kind == k) {
return true;
}
}
return false;
}
private void exec(RuleGroup rg ) {
if (!executed.contains(rg)) {
rg.exec(this);
executed.add(rg);
}
}
public void collectClasses(Set<ClassCase> seen) {
seen.add(this);
for (ClassCase cc : supertypes) {
cc.collectClasses(seen);
}
}
public String getID() {
if (name == null) {
throw new Error("Access to uninitialized ClassCase");
} else {
return name;
}
}
public final String getName() {
if (name == null) {
return "ClassCase uninited@" + hashCode();
} else {
return name;
}
}
@Override
public boolean equals(Object obj) {
return obj instanceof ClassCase && getID().equals(((ClassCase)obj).getID());
}
@Override
public int hashCode() {
return getID().hashCode();
}
@Override
public String toString() {
return getName();
}
}