1/*
2 * Copyright (c) 2005, 2015, 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 jdk.test.lib.jittester.types;
25
26import java.util.Collection;
27import java.util.HashSet;
28import java.util.TreeSet;
29import jdk.test.lib.jittester.ProductionParams;
30import jdk.test.lib.jittester.Symbol;
31import jdk.test.lib.jittester.SymbolTable;
32import jdk.test.lib.jittester.Type;
33import jdk.test.lib.jittester.TypeList;
34
35public class TypeKlass extends Type {
36    private TypeKlass parentKlass;
37    private final HashSet<String> parentsList;
38    private final HashSet<String> childrenList;
39    private final HashSet<Symbol> symbolsSet;
40    private int flags;
41
42    public static final int NONE = 0x00;
43    public static final int FINAL = 0x01;
44    public static final int INTERFACE = 0x02;
45    public static final int ABSTRACT = 0x04;
46
47
48    public TypeKlass(String name) {
49        this(name, NONE);
50    }
51
52    public TypeKlass(String name, int flags) {
53        super(name);
54        this.flags = flags;
55        parentsList = new HashSet<>();
56        childrenList = new HashSet<>();
57        symbolsSet = new HashSet<>();
58    }
59
60    public boolean addSymbol(Symbol s) {
61        return symbolsSet.add(s);
62    }
63
64    public boolean addAllSymbols(Collection<? extends Symbol> symbols) {
65        return symbolsSet.addAll(symbols);
66    }
67
68    public boolean containsSymbol(Symbol s) {
69        return symbolsSet.contains(s);
70    }
71
72    public boolean removeSymbol(Symbol s) {
73        return symbolsSet.remove(s);
74    }
75
76    public boolean removeAllSymbols(Collection<? extends Symbol> symbols) {
77        return symbolsSet.removeAll(symbols);
78    }
79
80    @Override
81    protected void exportSymbols() {
82        symbolsSet.stream().forEach(SymbolTable::add);
83    }
84
85    public void setParent(TypeKlass p) {
86        parentKlass = p;
87    }
88
89    public void addParent(String p) {
90        parentsList.add(p);
91    }
92
93    public void addChild(String c) {
94        childrenList.add(c);
95    }
96
97    protected void removeParent(String p) {
98        parentsList.remove(p);
99    }
100
101    protected void removeChild(String c) {
102        childrenList.remove(c);
103    }
104
105    public HashSet<String> getParentsNames() {
106        return parentsList;
107    }
108
109    public HashSet<String> getChildrenNames() {
110        return childrenList;
111    }
112
113    @Override
114    public boolean canCompareTo(Type t) {
115        return false;
116    }
117
118    @Override
119    public boolean canEquateTo(Type t) {
120        return true;
121    }
122
123    public TreeSet<TypeKlass> getAllParents() {
124        TreeSet<TypeKlass> result = new TreeSet<>();
125        parentsList.stream()
126                .map(TypeList::find)
127                .filter(parentKlass -> parentKlass != null)
128                .map(parentKlass -> (TypeKlass) parentKlass)
129                .forEach(parentKlass -> {
130                    result.add(parentKlass);
131                    result.addAll(parentKlass.getAllParents());
132        });
133        return result;
134    }
135
136    public TreeSet<TypeKlass> getAllChildren() {
137        TreeSet<TypeKlass> r = new TreeSet<>();
138        childrenList.stream()
139                .map(TypeList::find)
140                .filter(childKlass -> childKlass != null)
141                .map(childKlass -> (TypeKlass) childKlass)
142                .forEach(childKlass -> {
143                    r.add(childKlass);
144                    r.addAll(childKlass.getAllChildren());
145        });
146        return r;
147    }
148
149    @Override
150    public boolean canImplicitlyCastTo(Type t) {
151        // We can implicitly cast to anything up the hierarchy and to self
152        if (t instanceof TypeKlass) {
153            return equals(t) || getAllParents().contains(t);
154        }
155        return false;
156    }
157
158    // If canExplicitlyCastTo() returns true in this case it doesn't mean that
159    // it would really be successful. Since explicit casts are inherintly dynamic
160    // we cannot guarantee that no exception will occur.
161    @Override
162    public boolean canExplicitlyCastTo(Type t) {
163        if (equals(t)) {
164            return true;
165        }
166        if (t instanceof TypeKlass && !ProductionParams.disableDowncasts.value()) {
167            return getAllChildren().contains(t);
168        }
169
170        return false;
171    }
172
173    public boolean isFinal() {
174        return (flags & FINAL) > 0;
175    }
176
177    public void setFinal() {
178        flags |= FINAL;
179    }
180
181    public boolean isAbstract() {
182        return (flags & ABSTRACT) > 0;
183    }
184
185    public void setAbstract() {
186        flags |= ABSTRACT;
187    }
188
189    public boolean isInterface() {
190        return (flags & INTERFACE) > 0;
191    }
192
193    public TypeKlass getParent() {
194        return parentKlass;
195    }
196}
197