1/*
2 * Copyright (c) 2013, 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/*
25 * @test
26 * @bug 8011590
27 * @summary Check modeling of default methods
28 * @author Joseph D. Darcy
29 */
30
31import java.util.Objects;
32import java.lang.reflect.*;
33import java.lang.annotation.*;
34
35import static java.lang.reflect.Modifier.*;
36
37public class DefaultMethodModeling {
38    public static void main(String... args) {
39        int failures = 0;
40
41        Class<?>[] classes = {SuperC.class, SuperCchild.class,
42                              SuperI.class, SuperIchild.class,
43                              SuperIwithDefault.class, SuperIwithDefaultChild.class,
44                              Base.class, Combo1.class, Combo2.class,
45                              SonSuperIwithDefault.class, DaughterSuperIwithDefault.class, GrandchildSuperIwithDefault.class, D.class,
46                              B.class, C.class, B1.class, D1.class
47        };
48
49        for(Class<?> clazz : classes) {
50            System.err.println(clazz.toString());
51            for(Method m : clazz.getMethods()) {
52                if (m.getDeclaringClass() != java.lang.Object.class)
53                    failures += testMethod(m);
54            }
55        }
56
57        if (failures > 0)
58            throw new RuntimeException();
59    }
60
61    private static int testMethod(Method m) {
62        ExpectedModel em = Objects.requireNonNull(m.getAnnotation(ExpectedModel.class));
63        boolean failed = false;
64
65        if (m.getModifiers() != em.modifiers()) {
66            failed = true;
67            System.err.printf("Unexpected modifiers %d; expected %d%n", m.getModifiers(), em.modifiers());
68        }
69
70        if (m.isDefault() != em.isDefault()) {
71            failed = true;
72            System.err.printf("Unexpected isDefualt %b; expected b%n", m.isDefault(), em.isDefault());
73        }
74
75        if (!m.getDeclaringClass().equals(em.declaringClass())) {
76            failed = true;
77            System.err.printf("Unexpected isDefualt %s; expected %s%n",
78                              m.getDeclaringClass().toString(), em.declaringClass().toString());
79        }
80
81        return (!failed) ? 0 :1;
82    }
83}
84
85@Retention(RetentionPolicy.RUNTIME)
86@interface ExpectedModel {
87    boolean isDefault() default false;
88    int modifiers() default PUBLIC;
89    Class<?> declaringClass();
90}
91
92abstract class SuperC {
93    @ExpectedModel(modifiers=PUBLIC|ABSTRACT, declaringClass=SuperC.class)
94    public abstract void foo();
95
96    @ExpectedModel(declaringClass=SuperC.class)
97    public void bar() {
98        ;
99    }
100}
101
102class SuperCchild extends SuperC {
103    @ExpectedModel(declaringClass=SuperCchild.class)
104    @Override
105    public void foo() {;}
106}
107
108// -=-=-=-
109
110interface SuperI {
111    @ExpectedModel(modifiers=PUBLIC|ABSTRACT, declaringClass=SuperI.class)
112    void foo();
113
114    @ExpectedModel(modifiers=PUBLIC|ABSTRACT, declaringClass=SuperI.class)
115    void bar();
116}
117
118class SuperIchild implements SuperI {
119    @ExpectedModel(declaringClass=SuperIchild.class)
120    public void foo() {;}
121
122    @ExpectedModel(declaringClass=SuperIchild.class)
123    public void bar() {;}
124}
125
126// -=-=-=-
127
128interface SuperIwithDefault {
129    @ExpectedModel(modifiers=PUBLIC|ABSTRACT, declaringClass=SuperIwithDefault.class)
130    void foo();
131
132    @ExpectedModel(isDefault=true, declaringClass=SuperIwithDefault.class)
133    default void bar() {
134        ;
135    }
136}
137
138class SuperIwithDefaultChild implements SuperIwithDefault {
139    @ExpectedModel(declaringClass=SuperIwithDefaultChild.class)
140    @Override
141    public void foo() {;}
142}
143
144// -=-=-=-
145
146abstract class Base {
147    @ExpectedModel(modifiers=PUBLIC|ABSTRACT, declaringClass=Base.class)
148    public abstract void baz();
149
150    @ExpectedModel(declaringClass=Base.class)
151    public void quux() {;}
152}
153
154abstract class Combo1 extends Base implements SuperI {
155    @ExpectedModel(declaringClass=Combo1.class)
156    public void wombat() {}
157}
158
159abstract class Combo2 extends Base implements SuperIwithDefault {
160    @ExpectedModel(declaringClass=Combo2.class)
161    public void wombat() {}
162}
163
164// -=-=-=-
165
166interface SonSuperIwithDefault extends SuperIwithDefault {
167    @ExpectedModel(modifiers=PUBLIC|ABSTRACT, declaringClass=SonSuperIwithDefault.class)
168    void baz();
169
170    @ExpectedModel(isDefault=true, declaringClass=SonSuperIwithDefault.class)
171    default void bazD() {;}
172}
173
174interface DaughterSuperIwithDefault extends SuperIwithDefault {
175    @ExpectedModel(modifiers=PUBLIC|ABSTRACT, declaringClass=DaughterSuperIwithDefault.class)
176    void quux();
177
178    @ExpectedModel(isDefault=true, declaringClass=DaughterSuperIwithDefault.class)
179    default void quuxD() {;}
180}
181
182interface GrandchildSuperIwithDefault extends SonSuperIwithDefault, DaughterSuperIwithDefault {
183    @ExpectedModel(modifiers=PUBLIC|ABSTRACT, declaringClass=GrandchildSuperIwithDefault.class)
184    void wombat();
185
186    @ExpectedModel(isDefault=true, declaringClass=GrandchildSuperIwithDefault.class)
187    default void wombatD() {;}
188
189}
190
191class D implements GrandchildSuperIwithDefault {
192    @ExpectedModel(declaringClass=D.class)
193    public void wombat(){}
194
195    @ExpectedModel(declaringClass=D.class)
196    public void  baz(){}
197
198    @ExpectedModel(declaringClass=D.class)
199    public void foo(){}
200
201    @ExpectedModel(declaringClass=D.class)
202    public void quux(){}
203}
204
205class D1 implements SonSuperIwithDefault, DaughterSuperIwithDefault {
206    @ExpectedModel(declaringClass=D1.class)
207    public void foo(){}
208
209    @ExpectedModel(declaringClass=D1.class)
210    public void  baz(){}
211
212    @ExpectedModel(declaringClass=D1.class)
213    public void quux(){}
214}
215
216// -=-=-=-
217
218// What does re-abstraction look like?
219
220class A implements SuperIwithDefault {
221    @ExpectedModel(declaringClass=A.class)
222    @Override
223    public void foo(){;}
224}
225
226abstract class B extends A {
227    @ExpectedModel(modifiers=PUBLIC|ABSTRACT, declaringClass=B.class)
228    @Override
229    public abstract void bar();
230}
231
232class C extends B implements SuperIwithDefault {
233    @ExpectedModel(declaringClass=C.class)
234    public void bar(){}
235}
236
237abstract class A1 implements SonSuperIwithDefault {
238    @ExpectedModel(modifiers=PUBLIC|ABSTRACT, declaringClass=A1.class)
239    public abstract void baz();
240
241    @ExpectedModel(modifiers=PUBLIC|ABSTRACT, declaringClass=A1.class)
242    public abstract void foo();
243}
244
245class B1 extends A1 {
246    @ExpectedModel(declaringClass=B1.class)
247    @Override
248    public void foo(){;}
249
250    @ExpectedModel(declaringClass=B1.class)
251    @Override
252    public void baz(){}
253}
254